CUDA заставляет OpenMP работать в однопоточном режиме

Я написал программу CUDA SGEMM, и когда я захотел проверить скорость с помощью многопоточной реализации ЦП, она не смогла работать в многопоточном режиме. Я изолировал реализацию ЦП в отдельном файле, собрал ее и запустил, и проблем не возникло. Код в .cc и изолированном .cu (одинаковый):

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 поток», и выполнение действительно сериализуется. В то время как изолированный чистый исполняемый файл 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)

Может кто-нибудь сказать мне, что здесь происходит? Почему я не могу правильно использовать многопоточность OpenMP в программе CUDA? Кстати, если вы хотите знать, A, B, C можно распределить с помощью .cc или new, и это не повлияет на тот факт, что я не могу не запускать программу с более чем одним потоком, даже если функция процессора должна быть разделен с помощью nvcc, скомпилирован и запущен на процессоре.

возможно, вы неправильно скомпилировали данные. при компиляции кодов CUDA с nvcc, использующих OpenMP, обычно необходимо передать определенные параметры компиляции в nvcc, включая, например (если в Linux) -Xcompiler -fopenmp. Я понятия не имею, делает ли это ваш Cmake или нет, но я бы определенно отметил этот вопрос cmake.

Robert Crovella 18.03.2024 15:19

вы можете найти пример того, как создать код OpenMP с помощью nvcc в примерах CUDA (хотя и не с помощью cmake).

Robert Crovella 18.03.2024 15:28

Всегда полезно проверить фактические команды компиляции, используемые с make VERBOSE=1. Это показывает, что -fopenmp не передается nvcc. В условии if (OPENMP_FOUND) вы меняете только параметры для языков CXX и C, а не для языка CUDA. set (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler ${OpenMP_CXX_FLAGS}"), кажется, работает для меня с точки зрения добавления -Xcompiler -fopenmp к команде компиляции. Хотя это может быть хрупким, поскольку зависит от того, OpenMP_CXX_FLAGS является ли флаг единым. Менее хрупкое решение потребовало бы дополнительных манипуляций с веревками.

paleonix 18.03.2024 17:00
--forward-unknown-to-host-compiler может быть способом добавить эти флаги, не беспокоясь о -Xcompiler.
paleonix 18.03.2024 17:02

Отвечает ли это на ваш вопрос? Используете openMP в коде хоста cuda?

paleonix 18.03.2024 17:12

@RobertCrovella Спасибо, оказывается, проблема в настройке CMake. Я удалил CMAKE_CXX_FLAGS и CMAKE_C_FLAGS и вместо этого добавил set (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${OpenMP_CXX_FLAGS}"), многопоточность omp может поддерживаться даже без -Xcompiler и -fopenmp (думаю, ${OpenMP_CXX_FLAGS} включает некоторые из них?)

Enigmatisms 19.03.2024 05:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как упоминал @RobertCrovella, мой код скомпилирован неправильно, и CMAKE_CUDA_FLAGS установлен неправильно. Решение довольно простое, используйте:

find_package(OpenMP REQUIRED)
if (OPENMP_FOUND)
  set (CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${OpenMP_CXX_FLAGS}")
endif ()

вместо установки флагов c и cxx в CMake. Я проверил содержимое ${OpenMP_CXX_FLAGS} через message, там написано -fopenmp (и ничего больше), поэтому не нужно писать -fopenmp еще раз. Кроме того, я могу скомпилировать код без -Xcompiler, и он работает правильно. Если проблема не исчезнет, ​​можно попробовать добавить этот флаг. Спасибо за комментарии @RobertCrovella и @paleonix.

Другие вопросы по теме