OpenMP中可重用的私有动态分配数组
发布时间:2020-12-16 09:51:18 所属栏目:百科 来源:网络整理
导读:我使用OpenMP和MPI来并行化c中的一些矩阵运算.在矩阵上运行的一些函数是用Fortran编写的. Fortran函数需要传递一个缓冲区数组,该数组仅在函数内部使用.目前我在每个并行部分分配缓冲区,类似于下面的代码. int i = 0;int n = 1024; // Actually this is read
我使用OpenMP和MPI来并行化c中的一些矩阵运算.在矩阵上运行的一些函数是用Fortran编写的. Fortran函数需要传递一个缓冲区数组,该数组仅在函数内部使用.目前我在每个并行部分分配缓冲区,类似于下面的代码.
int i = 0; int n = 1024; // Actually this is read from command line double **a = createNbyNMat(n); #pragma omp parallel { double *buf; buf = malloc(sizeof(double)*n); #pragma omp for for (i=0; i < n; i++) { fortranFunc1_(a[i],&n,buf); } free(z); } // Serial code and moving data around in the matrix a using MPI #pragma omp parallel { double *buf; buf = malloc(sizeof(double)*n); #pragma omp for for (i=0; i < n; i++) { fortranFunc2_(a[i],buf); } free(z); } // and repeat a few more times. 我知道使用类似于下面的代码的方法可以避免重新分配缓冲区,但我很好奇是否有更简单的方法或OpenMP中的一些内置功能来处理这个问题.无论是否在我们正在编译的系统上存在OpenMP,能够在没有大量编译器指令的情况下编译代码将是很好的. double **buf; buf = malloc(sizeof(double*) * num_openmp_threads); int i = 0; for (i = 0; i < num_openmp_threads; ++i) { buf[i] = malloc(sizeof(double) * n); } // skip ahead #pragma omp for for (i=0; i < n; i++) { fortranFunc1_(a[i],buf[current_thread_num]); } 解决方法
可以使用线程私有变量来完成它.那些在后续的并行区域中持续存在:
void func(...) { static double *buf; #pragma omp threadprivate(buf) #pragma omp parallel num_threads(nth) { buf = malloc(n * sizeof(double)); ... } #pragma omp parallel num_threads(nth) { // Access buf here - it is still allocated } #pragma omp parallel num_threads(nth) { // Free the memory in the last parallel region free(buf); } } 这里有几个要点需要注意.首先,分配buf的线程数应该与解除分配它的线程数相匹配.此外,如果中间存在并行区域并且它们与较大的团队一起执行,则可能不会在所有区域中分配buf.因此,建议您禁用OpenMP的动态团队大小功能,或者只使用上面显示的num_threads子句来修复每个并行区域的线程数. 其次,局部变量只有在静态时才能成为线程私有的.因此,该方法不适用于递归函数. 即使禁用了OpenMP支持,代码也应按预期编译和工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |