多线程 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 结果相比,答案完全错误。如果只有很少的准确性错误,我不会说错。此外,我观察到程序在这些条件下表现良好:
- 使用 icc 而不是 g++,
- 删除 -fopenmp 标志,
- 使用 g++&atlas 代替 icc&mkl
- 设置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
这里有一个 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 结果相比,答案完全错误。如果只有很少的准确性错误,我不会说错。此外,我观察到程序在这些条件下表现良好:
- 使用 icc 而不是 g++,
- 删除 -fopenmp 标志,
- 使用 g++&atlas 代替 icc&mkl
- 设置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