openmp - 使用 OpenMP 拆分 LAPACK 调用

标签 openmp lapack

我正在对我编写的例程进行代码调整,其中一部分执行两个可以同时完成的矩阵乘法。目前,我在第一个 DGEMM 上调用 DGEMM(来自 Intel 的 MKL 库),然后在第二个 DGEMM 上调用。每次调用都会使用我机器上的全部 12 个内核。我希望它同时执行两个 DGEMM 例程,每个例程使用 6 个内核。我感觉这是一件简单的事情,但一直无法找到/理解如何实现这一点。我遇到的主要问题是 OpenMP 必须从一个线程调用 DGEMM 例程,但每次调用能够使用 6 个线程。哪个指令最适合这种情况?它需要嵌套的编译指示吗?

因此,作为更一般性的说明,我如何将(在我的例子中为 12 个)核心划分为多个集合,然后从一个线程运行一个例程,该线程使用其集合中的所有线程。

谢谢!

最佳答案

您可以做的最接近的事情是让 OpenMP 并行区域与两个线程组一起执行,然后从每个线程调用 MKL。您必须在 MKL 中启用嵌套并行性(通过禁用动态线程),将 MKL 线程数固定为 6,并且必须使用 Intel 的编译器套件来编译代码。 MKL 本身使用 OpenMP 进行线程化,但它是 Intel 的 OpenMP 运行时。如果您碰巧使用其他编译器,例如GCC,其 OpenMP 运行时可能与英特尔的不兼容。

由于您没有指定语言,我提供了两个示例 - 一个使用 Fortran,另一个使用 C/C++:

Fortran:

call mkl_set_num_threads(6)
call mkl_set_dynamic(0)

!$omp parallel sections num_threads(2)
!$omp section
   call dgemm(...)
!$omp end section
!$omp section
   call dgemm(...)
!$omp end section
!$omp end parallel sections

C/C++:

mkl_set_num_threads(6);
mkl_set_dynamic(0);

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

一般来说,您不能为 MKL 创建线程子集(至少根据我目前的理解)。每个 DGEMM 调用将使用全局指定数量的 MKL 线程。请注意,MKL 操作可能会调整 CPU 的缓存大小,并且并行执行两个矩阵乘法可能没有好处。如果您有一个带有两个六核 CPU 的 NUMA 系统,每个 CPU 都有自己的内存 Controller (我怀疑您的情况就是这样),那么您可能会遇到这种情况,但您必须注意数据的放置位置并启用线程的绑定(bind)(固定)到核心。

关于openmp - 使用 OpenMP 拆分 LAPACK 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14390423/

相关文章:

c++ - 使用 SIMD 对稀疏矩阵中的内部迭代器进行特征迭代

c++ - glCallList 上的 OpenMP 段错误的 GLFW3(以及 glfw 中的其他地方)

c - 并行化阶乘计算

r - 从 R 中的三对角对称矩阵获取特征值,就像在 lapack dstev 中一样

r - R 是否在启动时创建了太多线程

c - 使用 dpotrs(Cholesky 分解)求解线性系统

c++ - OpenMP 最小值缩减和 std::min

c - OpenMP 和 C99 数据

c - 设置 LAPACKE 的带状矩阵格式

c++ - 在 Mac OS X 上安装 C++ Armadillo 库