Chinaunix

标题: OPENMP的一个恶心问题 [打印本页]

作者: snakedy    时间: 2012-10-08 17:01
标题: OPENMP的一个恶心问题
我在LINUX下使用g++编译器,做一个OPENMP的优化处理实验,代码如下:
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <strings.h>
  4. #include <time.h>
  5. #include <omp.h>

  6. int main()
  7. {
  8.   long long k = 20;
  9.   int i;
  10.   int j[10] = {101,102,103,104,105,106,107,108,109,110};
  11.   printf("begin k=%d\tj[0]=%d\n", k,j[0]);
  12.   time_t t, t1;
  13.   t = time(NULL);
  14. omp_set_num_threads(7);
  15. #pragma omp parallel for
  16. for(i = 0; i < 7; i++)
  17. {
  18.                 int rank = omp_get_thread_num();
  19.           int count = omp_get_num_threads();     
  20.           printf("Hello from thread %d of %d\n", rank, count);
  21.   for( k=0; k < 1000000000; k++)
  22.   {
  23.     j[k%10] = k*k;
  24.   }
  25. }
  26.         t1 = time(NULL);
  27.   printf("time = [%d]\n", t1 - t);
  28.   printf("end k=%d\tj[0]=%d\n", k,j[0]);
  29. }
复制代码
分别采用OPENMP编译与不采用OPENMP编译的方式结果如下:

采用OPENMP的情况
begin k=20        j[0]=101
Hello from thread 0 of 7
Hello from thread 3 of 7
Hello from thread 4 of 7
Hello from thread 5 of 7
Hello from thread 6 of 7
Hello from thread 1 of 7
Hello from thread 2 of 7
time = [72]
end k=1000000000        j[0]=-11782044

不采用OPENMP的情况
begin k=20        j[0]=101
Hello from thread 0 of 1
Hello from thread 0 of 1
Hello from thread 0 of 1
Hello from thread 0 of 1
Hello from thread 0 of 1
Hello from thread 0 of 1
Hello from thread 0 of 1
time = [27]
end k=1000000000        j[0]=-11782044

采用OPENMP的的情况反而效率变低了,我的LINUX环境是
Linux FC14-1 2.6.35.14-106.fc14.x86_64 #1 SMP Wed Nov 23 13:07:52 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux, 2CPU, 8核(所以才用7个线程)

请那位使用过openmp的高手指点一下,我才vs2008上实验一个类似的程序,效果也是使用openmp时效率大幅下降了,很奇怪。
作者: snakedy    时间: 2012-10-08 17:20
看来用OPENMP提高软件性能的人比较少呀,大家谁知道给点思路也成呀。
作者: hellioncu    时间: 2012-10-08 17:22
没用过openmp,不过我觉得问题出在j上,这个数组被多个线程修改,会导致缓存失效,应该把j这个数组打散。
具体搜索 false sharing。
作者: snakedy    时间: 2012-10-08 17:30
其实,j这个数组我就是想做一个公式,或者一个处理随便编的,楼上说的我去试试,看是否是多个线程同时访问同一缓冲区造成的,其实这个循环不是一开始就效率下降的,内部循环次数减少一些时效率是提高状态,很奇怪
作者: snakedy    时间: 2012-10-08 17:34
定义了一个变量zz,将原有公式转换成zz += k * k;结果发现效率还是不比串行的效率
作者: snakedy    时间: 2012-10-08 17:47
楼上说的很有道理,我将程序的循环修改为#pragma omp parallel for private(zz),即将zz变量私有化后,运算从14秒瞬间变为0,不过结果好像就不对了,不过可以肯定的是openmp内部线程管理对共享资源访问是有一定的特殊处理的
作者: snakedy    时间: 2012-10-09 11:04
我的问题已经解决了,在此做一个总结,以便遇到相同问题的兄弟参考,除了上述问题会影响运算效率外,在OPENMP环境下,每个调用的函数层数也会影响运算效率,即如果一个算法中调用多个嵌套函数的话,用OPENMP并行它,运算结果可能还不如串行效率高,个人猜测是分配同一函数的堆栈太多,就像递归调用一样对系统资源以及访问效率都会有一定影响。尽量让自己并行部分“干净”一点是提高效率的最好的方法。
作者: fender0107401    时间: 2012-10-09 11:32
我用OpenMP的效果也是性能下降。
作者: zhujiang73    时间: 2012-10-09 12:05
fender0107401 发表于 2012-10-09 11:32
我用OpenMP的效果也是性能下降。



   这个需要调试,加锁操作要尽量少,这样基本可以有 N (CPU数) 倍的速度。
作者: snakedy    时间: 2012-10-09 13:42
其实这次的心得就是,使用OPENMP比较简单,但是需要对原有代码进行并行优化。
作者: egmkang    时间: 2012-10-09 16:35
本帖最后由 egmkang 于 2012-10-09 16:36 编辑

忽略,当我没说
作者: dyyseo    时间: 2012-10-10 16:18
看来用OPENMP提高软件性能的人比较少呀,大家谁知道给点思路也成呀。
作者: yezj2004    时间: 2012-10-12 09:58
也是支持,我代表大家顶你了
作者: 1407101    时间: 2012-10-12 16:22
个人觉得应该private(k)。
作者: dyyseo    时间: 2012-10-17 16:13
没用过openmp,不过我觉得问题出在j上,这个数组被多个线程修改,会导致缓存失效,应该把j这个数组打散。
具体搜索 false sharing。
作者: tianyour    时间: 2012-10-19 11:16
确实是这样子的
作者: clife7801    时间: 2012-10-25 09:13
恶心问题哪都有。只要静下心来慢慢研究都是可以解决的




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2