为可变数量的内核编写多线程程序
Posted
技术标签:
【中文标题】为可变数量的内核编写多线程程序【英文标题】:writing multithread program for variable number of cores 【发布时间】:2013-01-20 12:56:31 【问题描述】:我正在编写一个有 4 个线程范围的程序。我正在使用 VC++ 6.0 并且不想仅使用 VC++ 的任何库。 (按规则)最佳线程数应根据内核数确定。
如何编写代码,根据不同的核心数创建不同的线程数???
我想关注下表
Cores | Threads
---------------
1 | 2
2 | 3
3+ | 4
有 1 个 GUI 和 3 个工作线程。所有工作线程都使用循环缓冲区。我正在考虑实现 3 个工作线程,如下所示。
-
从文件读取 2. 处理文件 3. 处理后创建一个新文件。
所有这 3 个步骤针对每个输入文件按顺序完成。
会有大量文件需要处理(1000+)
我知道如何检测核心。也可以有 if then else 方式。但是,按照“if then else”的方式管理代码似乎将是一项艰巨的任务。
在这种情况下有什么标准的方式来管理代码吗?
【问题讨论】:
您需要添加有关程序结构的更多信息。是所有线程都合作做一件事,还是都有不同的目的?如果分开,4个任务应该由2个或3个线程完成时,哪些任务将由哪个线程完成? 线程作业怎么样。我的意思是如果 2 核然后 3 线程执行任务,如果 4 核然后 ??工作会不会增加?? 清楚地说明你的问题,可能有一些例子。 我不清楚这里的问题是什么?你到底想解决什么问题? 我的建议是不要担心。一直做4个线程。您将无法衡量任何差异。现在,如果您可以在具有 16 个内核的机器上运行,那么这可能很重要。 【参考方案1】:你可以使用std::hardware_concurrency:
#include <iostream>
#include <thread>
int main()
std::cout << "Number of available cores on this system (hint): "
<< std::thread::hardware_concurrency() << "\n";
然后启动适当数量的std::threads。
【讨论】:
-1。那不是问题。他知道如何检测内核数,问题不在于知道实现支持的并发线程数。 @Nawaz 你说得对,我刚刚看到了。仔细阅读问题,我无法弄清楚要问什么。 即使我想不通,这就是我对这个问题发表评论的原因。【参考方案2】:暂时,让我们忽略 GUI 线程,因为它总是一样的。
对于工作线程,您基本上创建的线程数量与核心相同,最多三个,因此您需要类似:
HANDLE worker_threads[3];
int num_threads = min(num_cores, 3);
for (int i=0; i<num_threads; i++)
worker_threads[i] = CreateThread(...);
现在,关于如何使用这些线程:简短的回答是我不会按照您在问题中描述的那样做。采取三个需要按顺序执行的步骤,并将它们跨线程分解是没有意义的。事实上,我完全会避免将线程专门用于特定类型的任务。
相反,我会保持线程通用,因此每个线程都可以执行三个任务中的任何一个。使用要执行的任务队列。线程只是从队列中检索任务并执行它们。如果该任务导致另一个任务被执行,则该任务将与其余任务一起放回队列中。
由于您是在 C++ 中执行此操作,因此一种明显的实现方法是为所有任务创建一个基类:
class Task
public:
virtual int operator()() = 0;
;
然后让您的三种不同任务类型从中派生。然后你可能想要创建一个小的包装类来掩盖你正在处理指针以保持代码简单明了的事实。
【讨论】:
谢谢Jerry,只有一个线程更方便,我会按照你的建议做。【参考方案3】:由于问题不是很具体,很难猜测您需要什么。
一般而言,您可以创建 workers
来完成某项工作并通知您(通过回调或其他方式)结果。
然后,您只需在每次需要完成某事时创建一个新的worker
。 workers
的最大数量取决于内核的数量。有可能以某种方式将您想要执行的任务存储在队列中,并将它们提供给下一个免费的worker
。
如果你能以某种方式描述你想做的事情(也许是一个简化的例子),那么就有可能更好地帮助你。也许可以向您展示如何使工人设计符合您的目的。
【讨论】:
以上是关于为可变数量的内核编写多线程程序的主要内容,如果未能解决你的问题,请参考以下文章
QtConcurrent 与多线程 QThread 的多线程性能