直接问题:我有一个简单的循环,可能是一个计算密集型函数。让我们假设每次迭代花费相同的时间(因此负载平衡应该很容易)。
#pragma omp parallel
{
#pragma omp for schedule(dynamic)
for ( int i=0; i < 30; i++ )
{
MyExpensiveFunction();
}
} // parallel block
为什么所有迭代都分配给一个线程?我可以添加一个:
std::cout << "tID = " << omp_get_thread_num() << "\n\n";
并打印出一堆零,只有最后一次迭代分配给线程1。
我的系统:我必须支持交叉编译。所以我正在使用gcc 4.4.3&amp; 4.5.0并且它们都按预期工作,但对于MS 2010,我看到上面的行为,其中29次迭代被分配给线程0并且一次迭代被分配给线程1。
真的奇怪:我花了一点时间才意识到这可能只是一个调度问题。我google'd并找到this website,如果你跳到底部有一个示例,必须是自动生成输出。使用动态和引导计划的所有迭代都会分配给线程零?? ??
非常感谢任何指导!!
答案 0 :(得分:2)
最有可能的原因是,这是因为Visual Studio中的OMP实现决定您没有足够的工作来将它放在多个线程上。如果只是增加迭代次数,那么您可能会发现其他线程的利用率更高。动态调度意味着实现只在需要时才会分叉新线程,因此如果它不需要它们,它就不会生成它们或为它们分配工作。
答案 1 :(得分:1)
如果每次迭代花费相同的时间,那么实际上您不需要动态调度,这会导致比静态调度策略更多的调度开销。 (静态,1)和(静态)应该没问题。
你能告诉我每次迭代的长度吗?关于你引用的例子(MSDN的schedulings示例),这是因为每次迭代的工作量都很小,所以第一个线程几乎可以工作。如果你真的增加了每次迭代的工作量(至少一个毫秒级),那么你会看到差异。
我做了很多与OpenMP调度策略相关的实验。 MSVC的动态调度实现很有效。我很确定你在每次迭代中的工作都太小了。