使用omp意外减速

时间:2016-02-15 16:53:07

标签: performance openmp nested-loops

我正在使用OMP尝试在小内核中获得一些加速。它基本上只是为成员资格查询无序集的向量。我试图进行优化,但令人惊讶的是我放慢了速度,我真的很好奇。

我的第一次传球是:

vector<unordered_set<uint16_t> > setList = getData();
#pragma omp parallel for default(shared) private(i, j) schedule(dynamic, 50)
for(i = 0; i < size; i++){
   for(j = 0; j < 500; j++){
      count = count + setList[i].count(val[j]);
   }
}

然后我想通过将setList [i]子表达式向上移动一级嵌套并将其保存在临时变量中,我可以通过执行以下操作来获得加速:

#pragma omp parallel for default(shared) private(i, j, currSet) schedule(dynamic, 50)
for(i = 0; i < size; i++){
   currSet = setList[i];
   for(j = 0; j < 500; j++){
      count = count + currSet.count(val[j]);
   }
}

我原本以为这可能会为“j”for循环的每次迭代节省一个负载,并获得加速,但它实际上减慢了约3倍。我的意思是整个内核运行时间大约是3倍。关于为什么会这样的想法?

谢谢!

2 个答案:

答案 0 :(得分:1)

添加一些整数真的不足以保证启动线程。

如果您忘记添加简化条款,您将遭受真正共享 - 所有线程都希望同时更新NSLog(@"Latitude: %g", self.coordLat); 变量。这使得所有内核都争夺包含tha变量的缓存行,这将对您的性能产​​生重大影响。

我刚注意到您将计划设置为动态。你不应该。此工作负载可以在编译时划分。所以不要指定时间表。

答案 1 :(得分:0)

正如已经陈述的循环间依赖性,即等待来自其他线程的数据的线程,或者多个线程连续访问的数据,可能导致并行程序经历减速并且应该作为经验法则避免。内置的功能(如缩减)可以收集单个结果并以优化的方式将它们编译在一起。

以下是与犹他大学类似案件中使用减少的一个很好的例子

int array[8] = { 1, 1, 1, 1, 1, 1, 1, 1};
int sum = 0, i;
#pragma omp parallel for reduction(+:sum)
for (i = 0; i < 8; i++) {
  sum += array[i];
}
printf("total %d\n", sum);

来源:http://www.eng.utah.edu/~cs4960-01/lecture9.pdf

作为旁白:只有在并行区域内的局部变量时才需要分配私有变量。在这两种情况下,都不需要将i声明为私有变量。

请参阅维基百科:https://en.wikipedia.org/wiki/OpenMP#Data_sharing_attribute_clauses

  

数据共享属性子句

     
      
  • 共享:共享并行区域内的数据,这意味着所有线程都可以同时查看和访问。默认情况下,工作共享区域中的所有变量都是共享的,但循环迭代计数器除外。

  •   
  • private :并行区域内的数据对每个线程都是私有的,这意味着每个线程都有一个本地副本并将其用作临时变量。未初始化私有变量,并且不维护该值以在并行区域之外使用。默认情况下,OpenMP循环结构中的循环迭代计数器是私有的。

  •   

请参阅堆栈交换答案:OpenMP: are local variables automatically private?