将线程移植到窗口.关键部分非常慢

joz*_*yqk 5 c c++ windows multithreading critical-section

我正在将一些代码移植到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和当前时间.

  • 单线程锁定的等待时间约为160毫秒
  • 要从堆栈弹出作业大约需要3ms
  • 休假需要大约3毫秒
  • 这项工作需要约1毫秒

(大致相同的Debug/Release,Debug需要更长的时间.我希望能够正确分析代码:P)

注释掉作业调用会使整个过程花费2秒钟(仍然超过linux).

我已经尝试了queryperformancecounter和timeGetTime,两者都给出了大致相同的结果.

AFAIK这个工作永远不会进行任何同步调用,但我不能解释减速,除非它确实如此.

我不知道为什么从堆栈复制并调用pop需要这么长时间.另一个令人困惑的事情是为什么对leave()的调用需要这么长时间.

任何人都可以推测为什么它运行如此缓慢?

我不会想到处理器的差异会带来100倍的性能差异,但它可能与双CPU有关吗?(必须在不同于内部核心的CPU之间进行同步).

顺便说一句,我知道std :: thread,但希望我的库代码能够与pre 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);
Run Code Online (Sandbox Code Playgroud)

和mutex类,删除linux #ifdef的东西......

CRITICAL_SECTION mutex;

...

Mutex::Mutex()
{
    InitializeCriticalSection(&mutex);
}
Mutex::~Mutex()
{
    DeleteCriticalSection(&mutex);
}
void Mutex::lock()
{
    EnterCriticalSection(&mutex);
}
void Mutex::unlock()
{
    LeaveCriticalSection(&mutex);
}
Run Code Online (Sandbox Code Playgroud)

jxh*_*jxh 0

看来您的 Windows 线程正面临超级争用。它们看起来完全是连续的。您的临界区有大约 7 毫秒的总处理时间和 32 个线程。如果所有线程都在锁上排队,队列中的最后一个线程只有在休眠大约 217 毫秒后才能运行。这与您观察到的 160 毫秒等待时间相差不远。

因此,如果线程除了进入临界区之外没有其他事情可做,执行工作,然后离开临界区,这就是我期望的行为。

尝试表征 linux 分析行为,并查看程序行为是否确实进行同类比较。