我编写了一个CUDA SGEMM程序,当我想用多线程CPU实现来测试速度时,它无法以多线程方式运行。我将 CPU 实现隔离在一个单独的
.cc
文件中,构建并运行它,没有任何问题。 .cu
和孤立的.cc
中的代码(相同):
void sgemm_cpu_multi_threading(
float* A, float* B, float* C,
float alpha, float beta, const int M, const int N, const int K
) {
#pragma omp parallel for num_threads(8)
for (int m = 0; m < M; m++) {
printf("%d thread(s) can be used\n", omp_get_num_threads());
for (int n = 0; n < N; n++) {
float psum = 0.0;
for (int k = 0; k < K; k++) {
psum += A[m * K + k] * B[k * N + n];
}
C[m * N + n] = C[m * N + n] * beta + psum * alpha;
}
}
}
int main() {
omp_set_num_threads(OMP_THREADS); // OMP_THREADS=8
// ...
sgemm_cpu_multi_threading(A, B, C, alpha, beta, M, N, K);
// ...
}
在CUDA程序中,printf总是输出“1 thread(s) can be use”并且执行确实是序列化的。虽然隔离的纯 cxx 可执行文件告诉我“可以使用8个线程”。 我的 CMakeLists.txt (CUDA)。对于孤立的cxx项目,我只删除与CUDA相关的行。
cmake_minimum_required(VERSION 3.10)
project(SGEMM CUDA CXX)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -fopenmp")
SET(COMPILE_CUDA True)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_ARCHITECTURES 75)
find_package(OpenMP REQUIRED)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
include_directories(
${CMAKE_SOURCE_DIR}/../
)
add_executable(matmul ./matmul.cu)
target_link_libraries(matmul pthread OpenMP::OpenMP_CXX)
有人可以告诉我这是怎么回事吗?为什么我无法在 CUDA 程序中正确使用 OpenMP 多线程?顺便说一句,如果你想知道,A、B、C 可以使用
new
或 cudaMallocHost
进行分配,这不会影响我不能用多个线程运行程序的事实,即使CPU 功能需要通过 nvcc 分离并在 CPU 上编译和运行。
正如@RobertCrovella 所提到的,我的代码未正确编译,
CMAKE_CUDA_FLAGS
未正确设置。解决方案非常简单,使用:
find_package(OpenMP REQUIRED)
if (OPENMP_FOUND)
set (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
而不是在 CMake 中设置 c 和 cxx 标志。我通过
${OpenMP_CXX_FLAGS}
检查了message
的内容,它写了-fopenmp
(没有别的),所以不需要再写-fopenmp
。另外,我可以在没有 -Xcompiler
的情况下编译代码,并且它可以正确运行。如果问题仍然存在,可以尝试添加此标志。感谢@RobertCrovella 和@paleonix 的评论。