【问题标题】:Reusable private dynamically allocated arrays in OpenMPOpenMP 中可重用的私有动态分配数组
【发布时间】:2014-03-24 19:25:54
【问题描述】:

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

【问题讨论】:

  • 否则我认为不需要fortran 标签。
  • 是的,你是对的,我删除了 Fortran 标签。这个问题类似,但关键区别在于动态分配的数组不会在另一个并行部分中重用。

标签: c mpi openmp


【解决方案1】:

可以使用线程私有变量来实现。这些在后续的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 支持,代码也应按预期编译和工作。

【讨论】:

    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-19
    • 1970-01-01
    • 1970-01-01
    • 2020-03-06
    相关资源
    最近更新 更多