888*_*888 11 c++ openmp boost-thread ppl
我有一个可以并行化的C++程序.我正在使用Visual Studio 2010,32位编译.
简而言之,该计划的结构如下
#define num_iterations 64 //some number
struct result
{
//some stuff
}
result best_result=initial_bad_result;
for(i=0; i<many_times; i++)
{
result *results[num_iterations];
for(j=0; j<num_iterations; j++)
{
some_computations(results+j);
}
// update best_result;
}
Run Code Online (Sandbox Code Playgroud)
由于每个some_computations()都是独立的(读取了一些全局变量,但没有修改全局变量),我并行化了内部for循环.
我的第一次尝试是使用boost :: thread,
thread_group group;
for(j=0; j<num_iterations; j++)
{
group.create_thread(boost::bind(&some_computation, this, result+j));
}
group.join_all();
Run Code Online (Sandbox Code Playgroud)
结果很好,但我决定尝试更多.
我试过OpenMP库
#pragma omp parallel for
for(j=0; j<num_iterations; j++)
{
some_computations(results+j);
}
Run Code Online (Sandbox Code Playgroud)
结果比boost::thread那些更差.
然后我尝试了ppl库并使用parallel_for():
Concurrency::parallel_for(0,num_iterations, [=](int j) {
some_computations(results+j);
})
Run Code Online (Sandbox Code Playgroud)
结果是最糟糕的.
我发现这种行为非常令人惊讶.由于OpenMP和ppl是为并行化而设计的,我希望得到更好的结果boost::thread.我错了吗?
为什么boost::thread给我更好的结果呢?
Ton*_*ion 10
OpenMP或PPL不会让人感到悲观.他们只是按照他们的说法去做,但是当你尝试对paralellize循环时,你应该考虑一些事情.
如果没有看到你如何实现这些东西,很难说真正的原因是什么.
此外,如果每次迭代中的操作都依赖于同一循环中的任何其他迭代,那么这将产生争用,这将减慢速度.您还没有显示您的some_operation函数实际执行的操作,因此很难判断是否存在数据依赖性.
可以真正并行化的循环必须能够使每次迭代完全独立于所有其他迭代运行,并且在任何迭代中都不会访问共享内存.因此,最好是将内容写入局部变量,然后在最后复制.
并非所有循环都可以并行化,它非常依赖于正在完成的工作类型.
例如,有助于并行化的是在屏幕缓冲区的每个像素上进行的工作.每个像素完全独立于所有其他像素,因此,线程可以进行循环的一次迭代并完成工作,而不需要等待迭代之间的循环内的共享存储器或数据依赖性.
此外,如果你有一个连续的数组,这个数组可能部分在一个缓存行中,如果你在线程A中编辑元素5然后在线程B中更改元素6,你可能会得到缓存争用,这也会减慢事情的速度,因为这些将驻留在同一缓存行中.一种称为虚假共享的现象.
在进行循环并行化时,需要考虑很多方面.