【发布时间】:2013-03-19 13:08:22
【问题描述】:
我目前正在试验多线程同步。对于背景,我有一组大约 100000 个对象 - 可能更多 - 我想以不同的方式每秒处理多次。
现在我最关心的是同步的性能。
这是我认为应该可以正常工作的(我省略了所有安全方面,因为这只是一个测试程序,如果出现错误,程序只会崩溃..)。我写了两个函数,第一个由程序的主线程执行,第二个由所有附加线程运行。
void SharedWorker::Start()
{
while (bRunning)
{
// Send the command to start task1
SetEvent(hTask1Event);
// Do task1 (on a subset of all objects) here
// Wait for all workers to finish task1
WaitForMultipleObjects(<NumberOfWorkers>, <ListOfTask1WorkerEvents>, TRUE, INFINITE);
// Reset the command for task1
ResetEvent(hTask1Event);
// Send the command to start task2
SetEvent(hTask2Event);
// Do task2 (on a subset of all objects) here
// Wait for all workers to finish task2
WaitForMultipleObjects(<NumberOfWorkers>, <ListOfTask2WorkerEvents>, TRUE, INFINITE);
// Reset the command for task2
ResetEvent(hTask2Event);
// Send the command to do cleanup
SetEvent(hCleanupEvent);
// Do some (on a subset of all objects) cleanup
// Wait for all workers to finish cleanup
WaitForMultipleObjects(<NumberOfWorkers>, <ListOfCleanupWorkerEvents>, TRUE, INFINITE);
// Reset the command for cleanup
ResetEvent(hCleanupEvent);
}
}
DWORD WINAPI WorkerThreads(LPVOID lpParameter)
{
while (bRunning)
{
WaitForSingleObject(hTask1Event, INFINITE);
// Unset finished cleanup
ResetEvent(hCleanedUp);
// Do task1 (on a subset of all objects) here
// Signal finished task1
SetEvent(hTask1);
WaitForSingleObject(hTask2Event, INFINITE);
// Reset task1 event
ResetEvent(hTask1);
// Do task2 (on a subset of all objects) here
// Signal finished task2
SetEvent(hTask2);
WaitForSingleObject(hCleanupEvent, INFINITE);
// Reset update event
ResetEvent(hTask2);
// Do cleanup (on a subset of all objects) here
// Signal finished cleanup
SetEvent(hCleanedUp);
}
return 0;
}
为了指出我的要求,我举个小例子: 假设我们从上面得到 100000 个对象,分成 8 个子集,每个子集 12500 个对象,这是一个具有 8 个逻辑内核的现代多核处理器。相关部分是时间。所有任务必须在大约 8ms 内完成。
我现在的问题是,我能否从拆分处理中获得显着的时间提升,或者通过事件进行同步是否过于昂贵?或者如果所有任务都需要以这种方式完成,是否还有其他方式可以以更少的工作或处理时间来同步线程?
【问题讨论】:
-
如果不了解您的任务及其资源要求(CPU、I/O)的更多信息,就不可能回答这个问题。一般来说,您应该尽量减少线程处于等待状态的时间。异步处理是线程间信号的一种替代方法,但这在您的任务执行中可能是不可能的。
-
哦,是的,抱歉,完全忘记了我的资源需求。任务 1 和 2 是纯 CPU,清理只是为了延迟从任务 2 中删除对象。不幸的是,异步处理是不可替代的,因为任务 1、任务 2 和清理是一个固定的顺序,必须保持顺序,并且必须在下一个任务之前完成任务可以开始了。
-
听起来您可能可以使用 OpenMP 之类的东西,而不是滚动您自己的线程/信号。这非常适合并行运行类似的、有序的任务。 msdn.microsoft.com/en-us/library/tt15eb9t(v=vs.110).aspx
-
感谢您对 OpenMP 的提示,我已经对它感兴趣了。你有一些使用 OpenMP 的经验吗?我从第一次性能测试中得到了一些意想不到的结果。使用循环测量固定次数迭代所花费的时间进行了测试(目前没有工作,因为我想知道哪个消耗的时间更少)。所以我以一百万次迭代为目标。在调试模式下,OpenMP 在 100% CPU 下以每秒 16.4k 次迭代 (ips) 运行,在发布模式下,在 100% CPU 下以 440k ips 运行。我的解决方案在两种模式下以 33% 的 CPU 运行速度为 46k ips。从我的角度来看,OpenMP 的结果很糟糕?
-
没有经验,只是听起来你的模式比求助于自定义任务调度更适合它
标签: c++ multithreading winapi events thread-synchronization