我正在使用 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], &n, 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], &n, buf[current_thread_num]);
}
可以使用线程私有变量来做到这一点。这些在后续的过程中仍然存在parallel
地区:
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 支持,代码也应该按预期编译和工作。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)