You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CUDA环境下OpenMP无法多线程运行问题求助

问题:CUDA项目中OpenMP多线程无法正常启用

现象描述

编写CUDA版SGEMM程序时,其中基于OpenMP实现的CPU多线程SGEMM在CUDA项目中始终串行执行,omp_get_num_threads()返回1;但将该CPU代码单独提取到纯C项目编译运行时,多线程正常工作,omp_get_num_threads()返回8。CUDA项目与纯C项目的CPU代码完全一致,内存分配方式(new/cudaMallocHost)不影响该问题。

相关代码

CPU多线程SGEMM实现

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() {
    const int OMP_THREADS = 8;
    omp_set_num_threads(OMP_THREADS);
    // ... 内存分配、初始化等逻辑
    sgemm_cpu_multi_threading(A, B, C, alpha, beta, M, N, K);
    // ... 后续处理
}

CUDA项目CMakeLists.txt

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)

问题原因

  1. CUDA编译未传递OpenMP参数:nvcc编译.cu文件时,会将CPU代码分离后调用宿主编译器(如gcc)处理,但当前CMake配置仅给CMAKE_CXX_FLAGS添加了OpenMP参数,未将这些参数传递给nvcc的编译流程。nvcc不会自动继承CMAKE_CXX_FLAGS的OpenMP选项,导致.cu文件中的CPU代码未启用OpenMP。
  2. 编译选项覆盖问题:手动设置CMAKE_CXX_FLAGS_RELEASE时直接赋值,可能覆盖了后续find_package(OpenMP)添加的编译参数,导致OpenMP未被正确启用。

解决方案

修改CMakeLists.txt,为CUDA编译显式传递OpenMP参数,并调整编译选项的设置方式:

cmake_minimum_required(VERSION 3.10)

project(SGEMM CUDA CXX)

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release")
endif()

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_ARCHITECTURES 75)

find_package(OpenMP REQUIRED)
if (OPENMP_FOUND)
  # 为C/CXX添加OpenMP编译参数
  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
  # 将OpenMP参数传递给nvcc调用的宿主编译器
  set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler ${OpenMP_CXX_FLAGS}")
endif()

# 用追加方式设置Release编译选项,避免覆盖已有参数
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} $ENV{CXXFLAGS} -O3 -Wall")
set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -O3")

include_directories(
    ${CMAKE_SOURCE_DIR}/../
)

add_executable(matmul ./matmul.cu)

target_link_libraries(matmul OpenMP::OpenMP_CXX)

关键改动说明

  • 添加CMAKE_CUDA_FLAGS设置,通过-Xcompiler将OpenMP参数传递给nvcc的宿主编译器,确保.cu文件中的CPU代码启用OpenMP。
  • 调整CMAKE_CXX_FLAGS_RELEASE的设置方式为追加,避免覆盖OpenMP相关参数。
  • 移除不必要的pthread链接(OpenMP::OpenMP_CXX已包含线程库依赖)。

内容的提问来源于stack exchange,提问作者Enigmatisms

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 23:54:58