gpt4 book ai didi

c - OpenMP 中可重用的私有(private)动态分配数组

转载 作者:太空狗 更新时间:2023-10-29 16:01:45 24 4
gpt4 key购买 nike

我正在使用 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]);
}

最佳答案

可以使用线程私有(private)变量来实现。这些在随后的平行区域中持续存在:

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 子句(如上所示)来固定每个并行区域的线程数。

其次,局部变量只有在它们是静态的情况下才能成为线程私有(private)的。因此,这种方法不适合在递归函数中使用。

即使禁用了 OpenMP 支持,代码也应该按预期编译和工作。

关于c - OpenMP 中可重用的私有(private)动态分配数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22592378/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com