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

时间:2013-08-26 11:02:38

标签: 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毫秒
  • 工作需要〜1ms

(大致相同的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);
}

2 个答案:

答案 0 :(得分:1)

首次输入时,窗口的CRITICAL_SECTION会以紧密循环旋转。它不会挂起调用EnterCriticalSection的线程,除非在旋转循环中经过了相当长的一段时间。因此,有32个线程竞争相同的关键部分将会烧毁并浪费大量的CPU周期。请尝试使用互斥锁(请参阅CreateMutex)。

答案 1 :(得分:0)

看起来您的Windows线程正面临超级争用。他们似乎完全连载。您的关键部分和32个线程的总处理时间约为7毫秒。如果所有线程都在锁上排队,那么队列中的最后一个线程将无法运行直到睡眠大约217ms。这距您观察到的160ms等待时间并不太远。

因此,如果线程没有其他任何事情要做,而不是进入临界区,那么就开始工作,然后离开临界区,这就是我期望的行为。

尝试描述linux分析行为,并查看程序行为是否真的与苹果比较。