多线程 MKL cblas_sgemm 出现 g++ 错误

Multi-thread MKL cblas_sgemm with g++ error

这里有一个 sgemm 程序的例子

#include <mkl.h>
#include <iostream>
#include <cstdlib>
#define ITERATION 1

int main()
{
  int ra = 128;
  int lda = 75;
  int ldb = 55;
  float* left = (float*)calloc(ra * lda, sizeof(float));
  float* right = (float*)calloc(ldb * lda, sizeof(float));
  float* ans = (float*)calloc(ra * ldb, sizeof(float));
  std::cout << "left " << std::endl;
  for (int i = 0; i < ra; ++i) {
    for (int j = 0; j < lda; ++j) {
      left[i * lda + j] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
      std::cout << left[i * lda + j] << " ";
    }
    std::cout << std::endl;
  }

  std::cout << "right " << std::endl;
  for (int i = 0; i < lda; ++i) {
    for (int j = 0; j < ldb; ++j) {
      right[i * ldb + j] = static_cast <float> (rand()) / static_cast <float> (RAND_MAX);
      std::cout << right[i * ldb + j] << " ";
    }
    std::cout << std::endl;
  }

  for (int i = 0; i < ITERATION; ++i) {
    cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, ra, ldb, lda, 1.0f, left, lda,
      right, ldb, 0.0f, ans, ldb);
  }

  std::cout << "ans " << std::endl;
  for (int i = 0; i < ra; ++i) {
    for (int j = 0; j < ldb; ++j) {
      std::cout << ans[i * ldb + j] << " ";
    }
    std::cout << std::endl;
  }

  return 0;
}

我通过选项 -fopenmp -lmkl_rt 用 g++ 编译这个程序,其中 OMP_NUM_THREADS 已设置为 16。

在 运行 程序之后,我发现与 matlab 结果相比,答案完全错误。如果只有很少的准确性错误,我不会说错。此外,我观察到程序在这些条件下表现良好:

  1. 使用 icc 而不是 g++,
  2. 删除 -fopenmp 标志,
  3. 使用 g++&atlas 代替 icc&mkl
  4. 设置OMP_NUM_THREADS=1

因此,我猜测问题可能出在-fopenmp标志上。你能帮我找出问题所在吗?谢谢!

g++ (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)

icc (ICC) 16.0.3 20160415

Linux core 2.6.32-279.el6.x86_64

根据 MKL link line advisor,您不需要将 -fopenmp 与单个动态库 -lmkl_rt 一起使用来启用多线程。由于您的 gcc 旧,这可能是个问题。

您可以尝试使用传统的动态链接并比较以下设置,看看是谁的问题。

线程 MKL + GNU OpenMP

Link options: -Wl,--no-as-needed -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_core -lmkl_gnu_thread -lpthread -lm -ldl           
Compile options: -fopenmp -m64 -I${MKLROOT}/include

线程 MKL + Intel OpenMP

Link options: -Wl,--no-as-needed -L${MKLROOT}/lib/intel64 -lmkl_intel_lp64 -lmkl_core -lmkl_intel_thread -liomp5 -lpthread -lm -ldl
Compile options: -m64 -I${MKLROOT}/include