我正在将一些代码移植到Windows,发现线程非常慢。 Windows上的任务需要300秒(两个至强E5-2670 8核2.6ghz = 16核)和3.5秒(xeon E5-1607 4核3ghz)。使用vs2012 express。
我有32个线程全部调用EnterCriticalSection(),弹出std :: stack的80字节作业,LeaveCriticalSection并做一些工作(总共250k个作业)。
在每个关键部分调用之前和之后,我打印线程ID和当前时间。
(大致相同的Debug / Release,Debug需要更长时间。我希望能够正确分析代码:P)
注释掉工作调用会使整个过程耗时2秒(仍然超过linux)。
我已经尝试过queryperformancecounter和timeGetTime,两者都给出了大致相同的结果。
AFAIK该作业从不进行任何同步调用,但我无法解释减速情况,除非确实如此。
我不知道为什么从堆栈复制并调用pop需要这么长时间。 另一个令人困惑的事情是为什么调用leave()需要这么长时间。
有人可以推测为什么它的运行速度这么慢吗?
我不会想到处理器的差异会带来100倍的性能差异,但是它可能与双CPU有关吗? (必须在不同于内部核心的CPU之间进行同步)。
顺便说一下,我知道std :: thread但是希望我的库代码能够用于预C ++ 11。
修改
//in a while(hasJobs) loop...
EVENT qwe1 = {"lock", timeGetTime(), id};
events.push_back(qwe1);
scene->jobMutex.lock();
EVENT qwe2 = {"getjob", timeGetTime(), id};
events.push_back(qwe2);
hasJobs = !scene->jobs.empty();
if (hasJobs)
{
job = scene->jobs.front();
scene->jobs.pop();
}
EVENT qwe3 = {"gotjob", timeGetTime(), id};
events.push_back(qwe3);
scene->jobMutex.unlock();
EVENT qwe4 = {"unlock", timeGetTime(), id};
events.push_back(qwe4);
if (hasJobs)
scene->performJob(job);
和mutex类,删除linux #ifdef的东西......
CRITICAL_SECTION mutex;
...
Mutex::Mutex()
{
InitializeCriticalSection(&mutex);
}
Mutex::~Mutex()
{
DeleteCriticalSection(&mutex);
}
void Mutex::lock()
{
EnterCriticalSection(&mutex);
}
void Mutex::unlock()
{
LeaveCriticalSection(&mutex);
}
答案 0 :(得分:1)
首次输入时,窗口的CRITICAL_SECTION会以紧密循环旋转。它不会挂起调用EnterCriticalSection的线程,除非在旋转循环中经过了相当长的一段时间。因此,有32个线程竞争相同的关键部分将会烧毁并浪费大量的CPU周期。请尝试使用互斥锁(请参阅CreateMutex)。
答案 1 :(得分:0)
看起来您的Windows线程正面临超级争用。他们似乎完全连载。您的关键部分和32个线程的总处理时间约为7毫秒。如果所有线程都在锁上排队,那么队列中的最后一个线程将无法运行直到睡眠大约217ms。这距您观察到的160ms等待时间并不太远。
因此,如果线程没有其他任何事情要做,而不是进入临界区,那么就开始工作,然后离开临界区,这就是我期望的行为。
尝试描述linux分析行为,并查看程序行为是否真的与苹果比较。