首页 > 解决方案 > OpenMP OpenBLAS 嵌套并行

问题描述

我们正在尝试并行运行两个 cblas_dgemm 实例。如果线程总数为 16,我们希望每个实例使用 8 个线程运行。目前,我们正在使用这样的结构:

#pragma omp parallel num_threads(2)
{
   if (omp_get_thread_num() == 0){
     cblas_dgemm(...);
   }else {
     cblas_dgemm(...);
   }
}

这是问题:

在顶层,有两个 OpenMP 线程,每个线程都在 if/else 块之一中处于活动状态。现在,我们希望那些调用 cblas_dgemm 函数的线程是并行的,并且在这些 cblas_dgemm 函数中,我们希望产生新线程。

为了设置每个 cblas_dgemm 内部的线程数,我们设置了相应的环境变量: setenv OPENBLAS_NUM_THREADS 8 但是,它似乎不起作用。如果我们测量每个并行调用的运行时间,运行时间值是相等的,但是当不使用嵌套并行并且环境变量 OPENBLAS_NUM_THREADS 设置为 1 时,它们等于单个 cblas_dgemm 调用的运行时间。

出了什么问题?以及我们如何才能拥有所需的行为?有什么方法可以知道 cblas_dgemm 函数中的线程数?

非常感谢您的时间和帮助

标签: multithreadingopenmpopenblas

解决方案


您尝试使用的机制称为“嵌套”,即在外部现有并行区域内创建新的并行区域已经处于活动状态。虽然大多数实现都支持嵌套,但默认情况下它是禁用的。尝试OMP_NESTED=true在命令行上设置或omp_set_nested(true)在代码中的第一个 OpenMP 指令之前调用。

我还将上面的代码更改为如下所示:

#pragma omp parallel num_threads(2)
{
#pragma omp sections
#pragma omp section
    {
        cblas_dgemm(...);
    }
#pragma omp section
    {
        cblas_dgemm(...);
    }
}

这样,代码也将只用一个线程计算正确的东西,将两个调用序列化到dgemm. 在您只有一个线程的示例中,代码会运行但会错过第二次dgemm调用。


推荐阅读