parallel_for创建了太多的类/体副本
TBB::parallel_for creates too many class/body copies?
我遵循了基本的parallel_for示例TBB。文档说明:
模板函数parallel_for要求主体对象有一个复制构造函数,调用该构造函数为每个工作线程创建一个(或多个)单独的副本。
我的算法需要每个并发工作线程运行一些内存。现在我在复制构造函数中分配内存。它可以工作,但这些是我的8线机器上的数字:在0-10000的范围内,我得到了大约2000个工作块(operator()
的调用),复制构造函数被调用了大约300次!这就是问题所在:300个内存分配中只需要8个。我检查了只有8个线程在运行,并且肯定不会同时使用超过8个类副本。
我假设副本的数量与线程的数量相关是完全错误的吗?有没有更好的方法来分配内存?
#include "tbb/tbb.h"
using namespace tbb;
class ApplyFoo {
float *const my_a;
public:
void operator()( const blocked_range<size_t>& r ) const {
float *a = my_a;
for( size_t i=r.begin(); i!=r.end(); ++i )
Foo(a[i]); // Foo uses the allocated memory
}
ApplyFoo( float a[] ) :
my_a(a)
{}
// the Copy-Constructor is called work every
ApplyFoo( const ApplyFoo& other ) :
my_a(a)
{
// Allocate some memory here...
}
~ApplyFoo()
{
// Free the memory here...
}
};
void ParallelApplyFoo( float a[], size_t n ) {
parallel_for(blocked_range<size_t>(0,n), ApplyFoo(a));
}
我假设副本的数量与线程的数量相关是完全错误的吗?
假设使用默认分区器(auto_partitioner
)的相关性是正确的,但是乘数足够大,并且取决于运行时条件,因此副本的数量可以与子分区的数量一样大。所以,这并不奇怪。
但是,可以通过指定增益大小来控制子范围的数量:
size_t p = task_scheduler_init::default_num_threads();
size_t grainsize = 2*n/p-1;
parallel_for(blocked_range<size_t>(0,n,grainsize), ApplyFoo(a));
这里的计算2*n/p-1
是因为在TBB中,粒度不是可能子范围的最小尺寸,而是用于决定是否分裂的阈值。
此外,对于具有parallel_for主体副本数量的分区程序的完全可预测的行为(独立于运行时条件),使用simple_partitioner
代替:
parallel_for(blocked_range<size_t>(0,n), ApplyFoo(a), simple_partitioner());
但是,它可能会导致大范围和小粒度的额外开销,因为它不聚合范围。
是否有更好的方法来分配内存?
是的,粒度大小并不是一个好方法,因为它会阻止TBB调度器更好地实现负载平衡。我建议使用线程本地存储容器。与基于编译器的TLS不同,它可以遍历值,以便在一个地方清理内存,即使原始线程已经消失。
- 在没有太多条件句的情况下,我如何避免被零除
- 错误:字符数组的初始值设定项太多
- 对象实例化调用构造函数的次数太多
- Levenshtein 两个文件的距离花费了太多时间
- 我有三个 getline,但是一旦编译,输入就太多了
- 将使用太多的纹理插值器 - 带旋转的着色器
- C/C++:socket() 创建在循环中失败,打开的文件太多
- 使用Visual Studio在虚幻引擎中创建一个新的类c ++给了我太多的错误
- C++:数组<>初始值设定项太多
- GLib-ERROR:为GWakeup创建管道:打开的文件太多
- C++,从文件读取到结构,然后读取到向量(结构被推入向量太多次,而不仅仅是一次)
- 我会导致太多内存泄漏,以至于我的计算机无响应吗?
- ZeroMq:打开的文件太多.在同一对象上连续增长的fd使用数
- 读取串行命令花费太多时间
- 为什么 Boost unordered_map 在第一次插入时需要太多时间?
- BRK(0) 花费的时间是否太多?
- Valgrind 声称内存释放中的自由空间太多
- 如果分支太多C++
- 压缩太多文件
- parallel_for创建了太多的类/体副本