2015-01-15 161 views
1

基于this问题,我有一个类,其构造函数只做一些分配,然后有一个实际完成这项工作的成员函数。我应该创建多少个线程?

我知道我将要构建的对象数量在[2,16]的范围内。实际的数字是一个用户参数。

我在创造我的对象for循环这样

for (int i = 0; i < n; ++i) { 
    roots.push_back(RKD<DivisionSpace>(...)); 
} 

然后在另一个for循环创建线程。每个线程对象的一大块叫build(),基于这样的逻辑:

如果矢量有n个元素,你有P个线程, 线程我只写元素

[中/ P,( i + 1)n/p)。

因此,举例来说,情况是这样的:

std::vector<RKD<Foo>> foos; 
// here is a for loop that pushes back 'n' objects to foos 

// thread A   // thread B     // thread C 
foos[0].build(); foos[n/3 + 0].build(); foos[2 * n/3 + 0].build(); 
foos[1].build(); foos[n/3 + 1].build(); foos[2 * n/3 + 1].build(); 
foos[2].build(); foos[n/3 + 2].build(); foos[2 * n/3 + 2].build(); 
...     ...       ... 

我遵循的方法是确定的线程p这样的数字:

p = min(n, P) 

其中n是我想要创建的对象的数量,并且P的返回值为std::thread::hardware_concurrencydealing与C++ 11的功能有一些问题后,我读了这一点:

即使hardware_concurrency实现,它不能依赖作为直接映射到内核的数量。这是标准所说的返回值 - 硬件线程上下文的数量。并继续说明 - 只应将此值视为提示如果您的计算机启用了超线程,则返回的值完全有可能是内核数量的两倍。如果你想得到可靠的答案,你需要使用你的操作系统提供的任何设施。 - Praetorian

这意味着我应该改变方法,因为这个代码是要从几个用户执行(我的意思是不仅在我的系统中,许多人将运行该代码)。所以,我想以一种既标准又高效的方式选择线程的数量。由于对象的数量相对较少,是否有一些规则可以遵循或什么?

+0

我不认为你所提供的报价意味着你需要改变的方法;它只是说这个值可能是* logical *(或* virtual *)内核的数量,这很好 - 如果它启用,您就希望利用超线程。如果您的处理器可以并行运行两倍,那么使用一半的线程没有意义。 – bogdan

+0

@bogdan如果你能回答分析你的观点,那会很棒,因为现在对我来说还不太清楚:/ – gsamaras

+0

OpenMP定义了[一些环境变量](https://gcc.gnu.org/onlinedocs /libgomp/Environment-Variables.html),它可以用来选择它将创建的最大线程数。你可以让你的应用程序检查具有相似名称的变量,如果它们不是由用户设置的,则回退到'std :: thread :: hardware_concurrency'。这就是我可能会做的。 – 5gon12eder

回答

1

只需挑选hardware_concurrency个线程的线程池,并按照先到先服务的原则排队项目。

如果系统中的其他进程以某种方式获得操作系统的优先级,那就这样吧。这仅仅意味着少于分配的池大小(例如P - 1)可以同时运行。从第一个可用的线程池完成build()开始并不重要 - 一个项目将从队列中选择下一个项目。

要真正避免线程在同一核心竞争,你可以

  • 使用信号量(进程间信号量,如果要真正地协调从单独的进程建设者线程)

  • 线程亲和力(以防止OS在下一个时间片上将特定线程调度到不同的核心上);可惜我不认为有标准,与平台无关,设置线程关联的方法(尚未)。

我看不出有什么令人信服的理由,使之更加复杂

+0

“只需选择hardware_concurrency线程的线程池”。你的意思是一个大小等于hardware_concurrency返回值的'std :: thread'池? – gsamaras

+0

是的。见例如这里http://stackoverflow.com/questions/22569805/boost-thread-throwing-exception-thread-resource-error-resource-temporarilyuna_25570554#22570554(“疯狂星期五奖金”) – sehe

+0

这个例子使用boost,这是我想要避免的,但是我明白了。所以每个线程只需要一个元素,不超过上述问题中的一个,对吧? – gsamaras

相关问题