【发布时间】:2019-07-23 15:48:40
【问题描述】:
我正在编写一个程序,当遇到最坏的情况时,它的计算成本相对较高。我尝试动态创建线程,这已被证明在大多数时间都可以工作,但是当最坏的情况出现时,执行速度超出了我分配给完成这些计算的时间,这很大程度上是由于这些线程的创建和销毁。这让我想到了我过去使用的想法,即在执行之前创建线程,而不是动态地创建和销毁它们,并让它们在执行计算之前等待一个条件而不是动态地创建它们。
通常我不会三思而后行,但因为我将在系统初始化时创建大量线程,所以我担心这将如何影响系统的性能。这就引出了一个问题:等待条件的线程如何影响系统,如果有的话?是在程序初始化期间创建线程,并且仅在我需要执行计算时才通知它们是解决此问题的正确方法,还是存在我不知道的更好的解决方案?我也考虑过使用线程池来做到这一点。线程池是否最适合这种情况?
您可能会发现有助于更好地回答此问题的一些信息:
--我正在使用 boost 库(版本 1_54_0)来对程序进行多线程处理。
--我使用的是 Windows 7 和 Visual Studio。
--如果我在程序初始化时创建线程,我将创建 200-1000 个线程(这个数字是预先确定为 #define 的,我不必每次需要进行计算时都使用所有线程)。
--每次我需要执行此计算时,所需的线程数都会有所不同;它取决于每次执行计算时收到的输入数量,但不能超过最大值(最大数量在编译时确定为#define)。
--我用的电脑是32核的。
如果这个问题没有达到标准,我很抱歉;我是一个新的堆栈溢出用户,所以请随时询问更多信息并批评我如何更好地解释情况和问题。提前感谢您的帮助!
更新
这里是源代码(部分变量已根据我公司的条款和条件进行了重命名)
for(int i = curBlob.boundingBoxStartY; i < curBlob.boundingBoxStartY + curBlob.boundingBoxHeight; ++i)
{
for(int j = curBlob.boundingBoxStartX; j < curBlob.boundingBoxStartX + curBlob.boundingBoxWidth; ++j)
{
for(int k = 0; k < NUM_FILTERS; ++k)
{
if((int)arrayOfBinaryValues[channel][k].at<uchar>(i,j) == 1)
{
for(int p = 0; p < NUM_FILTERS; ++p)
{
if(p != k)
{
if((curBlob.boundingBoxStartX + 1 < (curBlob.boundingBoxStartX + curBlob.boundingBoxWidth)) && ((int)arrayOfBinaryValues[channel][k].at<uchar>(i + 1,j) == 1))
++count;
if((curBlob.boundingBoxStartY + 1 < (curBlob.boundingBoxStartY + curBlob.boundingBoxHeight)) && ((int)arrayOfBinaryValues[channel][k].at<uchar>(i,j + 1) == 1))
++count;
}
}
}
}
}
}
提供的源代码是为了展示算法的复杂性。
【问题讨论】:
-
我怀疑您甚至“需要” 200-1000 个线程。当您达到 4 位数时,上下文切换的绝对水平将是可怕的。您可能需要考虑工作人员通过队列分派工作中的线程池。它消除了队列的启动/关闭时间,并且很可能会更好地并行化,特别是如果您的池是基于核心计数因素配置的。
-
@WhozCraig 200 到 1000 个线程对系统性能几乎没有影响,因为它们中的大多数将处于等待状态。现在我的机器有大约 500 个活动线程,CPU 基本上是 0%(不包括我看的时候似乎吃掉 CPU 的 Iceweasel)。但是,我完全同意这么多线程很可能毫无用处,而工作线程池会更合适。
-
@syam 我不是在谈论他们空闲的时候;我说的是他们嘎吱嘎吱的时候。我的窗外是一个停车场,停满了没有做任何事情的汽车,但这并不意味着在几个小时内他们都不会陷入可怕的交通拥堵中试图回家(并进入每个其他的方式)。我认为我们都同意 OP 应该考虑除了每个活动一个线程方法之外的替代方案。
-
感谢克雷格的洞察力。很好的比喻:)
-
即使使用 CPU 密集型线程,一旦就绪线程数超过内核数的两倍,与上下文切换相关的开销就会变平。在那之后,每秒中断的数量不会随着线程数量而神奇地增加,并且只有在中断时操作系统才能进行上下文切换。
标签: c++ multithreading boost