我正在将一些代码移植到 Windows,发现线程非常慢。该任务在 Windows 上需要 300 秒(两个至强 E5-2670 8 核 2.6ghz = 16 核),在 linux 上需要 3.5 秒(至强 E5-1607 4 核 3ghz)。使用vs2012 express。
我有 32 个线程都在调用 EnterCriticalSection(),弹出一个 80 字节的 std::stack 作业,LeaveCriticalSection 并做一些工作(总共 250k 作业)。
在每个关键部分调用之前和之后,我都会打印线程 ID 和当前时间。
- 单线程锁的等待时间约为 160ms
- 将作业从堆栈中弹出大约需要 3 毫秒
- 打电话请假大约需要 3 毫秒
- 这项工作大约需要 1 毫秒
(调试/发布大致相同,调试需要更长的时间。我希望能够正确分析代码: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);
和互斥类,删除了 linux #ifdef 东西......
CRITICAL_SECTION mutex;
...
Mutex::Mutex()
{
InitializeCriticalSection(&mutex);
}
Mutex::~Mutex()
{
DeleteCriticalSection(&mutex);
}
void Mutex::lock()
{
EnterCriticalSection(&mutex);
}
void Mutex::unlock()
{
LeaveCriticalSection(&mutex);
}