From df004e5787c3354b391aff83278ea61db2b58af1 Mon Sep 17 00:00:00 2001 From: userchba <1075002153@qq.com> Date: Sat, 31 Oct 2026 16:37:15 +0800 Subject: [PATCH] fix(gpu): support LibDDLA 0.0.6 public API --- include/RI/global/gpu/GPU_Backend.h | 87 +++++++++++++-------------- include/RI/ri/gpu/Dim.h | 6 +- include/RI/ri/gpu/GPU_Data_Input.h | 10 +-- include/RI/ri/gpu/GPU_Data_Mul.h | 15 +++-- include/RI/ri/gpu/GPU_Data_Output.h | 10 +-- include/RI/ri/gpu/GPU_Data_Tmp.h | 10 +-- unittests/gpu_symmetry/CMakeLists.txt | 9 ++- unittests/gpu_symmetry/README.md | 4 +- 8 files changed, 80 insertions(+), 71 deletions(-) diff --git a/include/RI/global/gpu/GPU_Backend.h b/include/RI/global/gpu/GPU_Backend.h index 17301e9..2520cb3 100644 --- a/include/RI/global/gpu/GPU_Backend.h +++ b/include/RI/global/gpu/GPU_Backend.h @@ -15,9 +15,7 @@ #if (defined(DDLA_USE_CUDA) + defined(DDLA_USE_HIP)) != 1 #error "__DDLA_RI requires exactly one of DDLA_USE_CUDA or DDLA_USE_HIP" #endif - #include - #include - #include + #include #elif defined(__MAGMA_RI) #include "Magmablas_Interface-Contiguous.h" @@ -28,6 +26,7 @@ #include +#include #include #include #include @@ -41,16 +40,12 @@ namespace GPU_Backend #ifdef __DDLA_RI using Int = int; - using Transpose = ddla::deblasOperation_t; + using Transpose = char; using Queue = ddla::DdlaHandle_t; - constexpr Transpose NoTrans = ddla::DEBLAS_OP_N; - constexpr Transpose Trans = ddla::DEBLAS_OP_T; - constexpr Transpose ConjTrans = ddla::DEBLAS_OP_C; + constexpr Transpose NoTrans = 'N'; + constexpr Transpose Trans = 'T'; + constexpr Transpose ConjTrans = 'C'; - inline ddla::deviceStream_t stream(Queue queue) - { - return static_cast(ddla::ddla_get_stream(queue)); - } #elif defined(__MAGMA_RI) using Int = magma_int_t; using Transpose = magma_trans_t; @@ -92,7 +87,7 @@ template Type_to_CPU data_to_CPU(const T_GPU data_gpu) #endif -inline void validate_local_gpu_count(const MPI_Comm& communicator) +inline void validate_local_gpu_count(const MPI_Comm& communicator, int device_count) { MPI_Comm local_communicator = MPI_COMM_NULL; if (MPI_Comm_split_type( @@ -105,12 +100,6 @@ inline void validate_local_gpu_count(const MPI_Comm& communicator) MPI_Comm_size(local_communicator, &local_size); MPI_Comm_free(&local_communicator); - int device_count = 0; -#ifdef __DDLA_RI - ddla::DEVICE_CHECK(ddla::deviceGetDeviceCount(&device_count)); -#elif defined(__MAGMA_RI) - device_count = Magma_Wrapper::magma_get_size(); -#endif if (device_count <= 0 || local_size > device_count) throw std::runtime_error( "LibRI requires at least one GPU per local MPI rank"); @@ -122,14 +111,24 @@ class Context explicit Context(const MPI_Comm& communicator) { #ifdef __DDLA_RI - validate_local_gpu_count(communicator); - ddla::ddla_init(queue_); - ddla::ddla_set(queue_, communicator); + ddla::DDLA_CHECK(ddla::ddlaInit(queue_, ddla::DdlaBackend::GPU)); + try + { + int device_count = 0; + ddla::DDLA_CHECK(ddla::ddlaGetDeviceCount(queue_, &device_count)); + validate_local_gpu_count(communicator, device_count); + ddla::DDLA_CHECK(ddla::ddlaSet(queue_, communicator)); + } + catch (...) + { + ddla::ddlaDestroy(queue_); + throw; + } #elif defined(__MAGMA_RI) MAGMA_CHECK_RI(magma_init()); try { - validate_local_gpu_count(communicator); + validate_local_gpu_count(communicator, Magma_Wrapper::magma_get_size()); } catch (...) { @@ -149,7 +148,7 @@ class Context ~Context() { #ifdef __DDLA_RI - ddla::ddla_destroy(queue_); + ddla::ddlaDestroy(queue_); #elif defined(__MAGMA_RI) if (queue_ != nullptr) magma_queue_destroy(queue_); @@ -166,28 +165,30 @@ class Context }; template -inline void allocate(T** pointer, std::size_t count) +inline void allocate(T** pointer, std::size_t count, Queue queue) { +#ifdef __DDLA_RI + ddla::DDLA_CHECK(ddla::ddlaMalloc(queue, pointer, count * sizeof(T))); +#elif defined(__MAGMA_RI) + (void)queue; if (count == 0) { *pointer = nullptr; return; } -#ifdef __DDLA_RI - ddla::DEVICE_CHECK(ddla::deviceMalloc(pointer, count * sizeof(T))); -#elif defined(__MAGMA_RI) MAGMA_CHECK_RI(magma_malloc(reinterpret_cast(pointer), count * sizeof(T))); #endif } template -inline void free(T* pointer) +inline void free(T* pointer, Queue queue) { if (pointer == nullptr) return; #ifdef __DDLA_RI - ddla::DEVICE_CHECK(ddla::deviceFree(pointer)); + ddla::DDLA_CHECK(ddla::ddlaFree(queue, pointer)); #elif defined(__MAGMA_RI) + (void)queue; MAGMA_CHECK_RI(magma_free(pointer)); #endif } @@ -199,9 +200,8 @@ inline void upload( if (count == 0) return; #ifdef __DDLA_RI - ddla::DEVICE_CHECK(deviceMemcpyAsync( - device_data, host_data, count * sizeof(T), - ddla::deviceMemcpyHostToDevice, stream(queue))); + ddla::DDLA_CHECK(ddla::ddlaMemcpy( + queue, device_data, host_data, count * sizeof(T))); #elif defined(__MAGMA_RI) magma_setvector_async( count, sizeof(T), host_data, 1, device_data, 1, queue); @@ -215,9 +215,8 @@ inline void download( if (count == 0) return; #ifdef __DDLA_RI - ddla::DEVICE_CHECK(deviceMemcpyAsync( - host_data, device_data, count * sizeof(T), - ddla::deviceMemcpyDeviceToHost, stream(queue))); + ddla::DDLA_CHECK(ddla::ddlaMemcpy( + queue, host_data, device_data, count * sizeof(T))); #elif defined(__MAGMA_RI) magma_getvector_async( count, sizeof(T), device_data, 1, host_data, 1, queue); @@ -229,8 +228,7 @@ inline void memset(void* pointer, int value, std::size_t bytes, Queue queue) if (bytes == 0) return; #ifdef __DDLA_RI - ddla::DEVICE_CHECK(deviceMemsetAsync( - pointer, value, bytes, stream(queue))); + ddla::DDLA_CHECK(ddla::ddlaMemset(queue, pointer, value, bytes)); #elif defined(__MAGMA_RI) MAGMA_CHECK_RI(magma_memset(pointer, value, bytes)); #endif @@ -239,8 +237,7 @@ inline void memset(void* pointer, int value, std::size_t bytes, Queue queue) inline void sync(Queue queue) { #ifdef __DDLA_RI - ddla::DEVICE_CHECK( - ddla::deviceStreamSynchronize(stream(queue))); + ddla::DDLA_CHECK(ddla::ddlaSynchronize(queue)); #elif defined(__MAGMA_RI) magma_queue_sync(queue); #endif @@ -257,10 +254,10 @@ inline void gemmVbatched( Int*& lda = transA == NoTrans ? k : m; Int*& ldb = transB == NoTrans ? n : k; Int*& ldc = n; - ddla::gemmVbatched( - transB, transA, n, m, k, + ddla::gemmVbatched( + queue, transB, transA, n, m, k, alpha, dB_array, ldb, dA_array, lda, - beta, dC_array, ldc, batch_count, queue); + beta, dC_array, ldc, batch_count); #elif defined(__MAGMA_RI) Magma_Interface::gemm_vbatched( transA, transB, m, n, k, @@ -290,14 +287,14 @@ inline void gemmVbatched2s( Int* lda_1 = transA_1 == NoTrans ? k_1 : m_1; Int* ldb_1 = transB_1 == NoTrans ? n_1 : k_1; Int* ldc_1 = n_1; - ddla::gemmVbatched2s( - transB_0, transA_0, n_0, m_0, k_0, + ddla::gemmVbatched2s( + queue, transB_0, transA_0, n_0, m_0, k_0, alpha_0, dB_array_0, ldb_0, dA_array_0, lda_0, beta_0, dC_array_0, ldc_0, transB_1, transA_1, n_1, m_1, k_1, alpha_1, dAB_array_1, ldb_1, lda_1, beta_1, dC_array_1, ldc_1, !C0_left, - batch_count, segment_sizes.data(), segment_sizes.size(), queue); + batch_count, segment_sizes.data(), segment_sizes.size()); #elif defined(__MAGMA_RI) Magma_Interface::gemm_vbatched_2s( transA_0, transB_0, m_0, n_0, k_0, diff --git a/include/RI/ri/gpu/Dim.h b/include/RI/ri/gpu/Dim.h index 0260872..39c59bf 100644 --- a/include/RI/ri/gpu/Dim.h +++ b/include/RI/ri/gpu/Dim.h @@ -16,6 +16,7 @@ namespace RI class Dim { public: + GPU_Backend::Queue queue_ = nullptr; void input(const int shape) { this->shapes.push_back(shape); @@ -27,14 +28,15 @@ class Dim void upload(GPU_Backend::Queue queue) { - GPU_Backend::allocate(&this->d_m, this->shapes.size() + 1); + this->queue_ = queue; + GPU_Backend::allocate(&this->d_m, this->shapes.size() + 1, queue); GPU_Backend::upload( this->shapes.size(), this->shapes.data(), this->d_m, queue); } ~Dim() { - GPU_Backend::free(this->d_m); + GPU_Backend::free(this->d_m, this->queue_); } int* data() const diff --git a/include/RI/ri/gpu/GPU_Data_Input.h b/include/RI/ri/gpu/GPU_Data_Input.h index cdb79e2..4bc2fb2 100644 --- a/include/RI/ri/gpu/GPU_Data_Input.h +++ b/include/RI/ri/gpu/GPU_Data_Input.h @@ -23,6 +23,7 @@ template class Input { public: + GPU_Backend::Queue queue_ = nullptr; using Tdata_GPU = GPU_Backend::Type_to_GPU; using Same_data_layout = std::integral_constant< bool, @@ -63,11 +64,12 @@ class Input // 将对应的 C, V, D 放在 d_Cs, d_Vs, d_Ds 上 void upload(GPU_Backend::Queue queue) { + this->queue_ = queue; std::vector h_data_begin(this->h_data.size()+1, 0); for(std::size_t i=1; ih_data[i-1].size(); - GPU_Backend::allocate(&this->d_data, h_data_begin.back()); + GPU_Backend::allocate(&this->d_data, h_data_begin.back(), queue); for(std::size_t i=0; ih_data.size(); ++i) GPU_Backend::upload( this->h_data[i].size(), this->h_data[i].data(), @@ -77,14 +79,14 @@ class Input std::vector d_array_(batchCount); // 记录每个batch的 d_data 指针(CPU) for(std::size_t i=0; id_data + this->h_array[i].pos + h_data_begin[this->h_array[i].thread_num]; - GPU_Backend::allocate(&this->d_array, batchCount); + GPU_Backend::allocate(&this->d_array, batchCount, queue); GPU_Backend::upload(batchCount, d_array_.data(), this->d_array, queue); } ~Input() { - GPU_Backend::free(this->d_data); - GPU_Backend::free(this->d_array); + GPU_Backend::free(this->d_data, this->queue_); + GPU_Backend::free(this->d_array, this->queue_); } private: diff --git a/include/RI/ri/gpu/GPU_Data_Mul.h b/include/RI/ri/gpu/GPU_Data_Mul.h index 31afefc..d28cdb4 100644 --- a/include/RI/ri/gpu/GPU_Data_Mul.h +++ b/include/RI/ri/gpu/GPU_Data_Mul.h @@ -20,6 +20,7 @@ template class Mul { public: + GPU_Backend::Queue queue_ = nullptr; using Tdata_GPU = GPU_Backend::Type_to_GPU; const Pack &insert_1st(const TA &Aa, const TAC &Ab, const Shape_Vector &shape) @@ -38,7 +39,8 @@ class Mul void upload_1st(GPU_Backend::Queue queue) { - GPU_Backend::allocate(&this->d_data, this->totalSize); + this->queue_ = queue; + GPU_Backend::allocate(&this->d_data, this->totalSize, queue); GPU_Backend::memset( this->d_data, 0, totalSize * sizeof(Tdata_GPU), queue); @@ -46,7 +48,7 @@ class Mul std::vector d_array_(batchCount); // 记录每个batch的 d_data 指针(CPU) for (std::size_t i = 0; i < batchCount; i++) d_array_[i] = this->d_data + this->h_array_1[i].pos; - GPU_Backend::allocate(&this->d_array_1, batchCount); + GPU_Backend::allocate(&this->d_array_1, batchCount, queue); GPU_Backend::upload( batchCount, d_array_.data(), this->d_array_1, queue); } @@ -65,20 +67,21 @@ class Mul // 在 GPU 上分配空间,并获取指针 void upload_2nd(GPU_Backend::Queue queue) { + this->queue_ = queue; const std::size_t batchCount = this->h_array_2.size(); std::vector d_array_2_(batchCount); // 记录每个batch的 d_data 指针(CPU) for (std::size_t i = 0; i < batchCount; i++) d_array_2_[i] = this->d_data + this->h_array_2[i].pos; - GPU_Backend::allocate(&this->d_array_2, batchCount); + GPU_Backend::allocate(&this->d_array_2, batchCount, queue); GPU_Backend::upload( batchCount, d_array_2_.data(), this->d_array_2, queue); } ~Mul() { - GPU_Backend::free(this->d_data); - GPU_Backend::free(this->d_array_1); - GPU_Backend::free(this->d_array_2); + GPU_Backend::free(this->d_data, this->queue_); + GPU_Backend::free(this->d_array_1, this->queue_); + GPU_Backend::free(this->d_array_2, this->queue_); } std::size_t totalSize = 0; // 总的数据数量 diff --git a/include/RI/ri/gpu/GPU_Data_Output.h b/include/RI/ri/gpu/GPU_Data_Output.h index ec0bcea..a97b3d8 100644 --- a/include/RI/ri/gpu/GPU_Data_Output.h +++ b/include/RI/ri/gpu/GPU_Data_Output.h @@ -25,6 +25,7 @@ template class Output { public: + GPU_Backend::Queue queue_ = nullptr; using Tdata_GPU = GPU_Backend::Type_to_GPU; using Same_data_layout = std::integral_constant< bool, @@ -46,7 +47,8 @@ class Output void upload(GPU_Backend::Queue queue) { - GPU_Backend::allocate(&this->d_data, this->totalSize); + this->queue_ = queue; + GPU_Backend::allocate(&this->d_data, this->totalSize, queue); GPU_Backend::memset( this->d_data, 0, totalSize * sizeof(Tdata_GPU), queue); @@ -54,7 +56,7 @@ class Output std::vector d_array_(batchCount); // 记录每个batch的 d_data 指针(CPU) for (std::size_t i = 0; i < batchCount; i++) d_array_[i] = this->d_data + this->h_array[i].pos; - GPU_Backend::allocate(&this->d_array, batchCount); + GPU_Backend::allocate(&this->d_array, batchCount, queue); GPU_Backend::upload(batchCount, d_array_.data(), this->d_array, queue); } @@ -83,8 +85,8 @@ class Output ~Output() { - GPU_Backend::free(this->d_data); - GPU_Backend::free(this->d_array); + GPU_Backend::free(this->d_data, this->queue_); + GPU_Backend::free(this->d_array, this->queue_); } private: diff --git a/include/RI/ri/gpu/GPU_Data_Tmp.h b/include/RI/ri/gpu/GPU_Data_Tmp.h index dd68b7c..7e9b29a 100644 --- a/include/RI/ri/gpu/GPU_Data_Tmp.h +++ b/include/RI/ri/gpu/GPU_Data_Tmp.h @@ -20,6 +20,7 @@ template class Tmp { public: + GPU_Backend::Queue queue_ = nullptr; using Tdata_GPU = GPU_Backend::Type_to_GPU; const Pack &insert(const Shape_Vector &shape) @@ -36,10 +37,11 @@ class Tmp std::vector upload( const std::size_t memory_limit, GPU_Backend::Queue queue) { + this->queue_ = queue; const std::size_t size_limit = std::min(this->totalSize, memory_limit / sizeof(Tdata_GPU)); const std::vector> h_array_segments = segment_points(this->h_array, size_limit); - GPU_Backend::allocate(&this->d_data, size_limit); + GPU_Backend::allocate(&this->d_data, size_limit, queue); GPU_Backend::memset( this->d_data, 0, size_limit * sizeof(Tdata_GPU), queue); @@ -48,7 +50,7 @@ class Tmp for(const auto &h_array_segment : h_array_segments) for(const Pack &pack : h_array_segment) d_array_.push_back(this->d_data + pack.pos); - GPU_Backend::allocate(&this->d_array, batchCount); + GPU_Backend::allocate(&this->d_array, batchCount, queue); GPU_Backend::upload(batchCount, d_array_.data(), this->d_array, queue); std::vector segments_size; @@ -83,8 +85,8 @@ class Tmp ~Tmp() { - GPU_Backend::free(this->d_data); - GPU_Backend::free(this->d_array); + GPU_Backend::free(this->d_data, this->queue_); + GPU_Backend::free(this->d_array, this->queue_); } std::size_t totalSize = 0; // 总的数据数量 diff --git a/unittests/gpu_symmetry/CMakeLists.txt b/unittests/gpu_symmetry/CMakeLists.txt index f385c36..f9af53f 100644 --- a/unittests/gpu_symmetry/CMakeLists.txt +++ b/unittests/gpu_symmetry/CMakeLists.txt @@ -20,13 +20,12 @@ target_link_libraries(test_lri_gpu_symmetry PRIVATE MPI::MPI_CXX OpenMP::OpenMP_CXX ${LAPACK_LIBRARIES} ${BLAS_LIBRARIES}) if(ENABLE_GPU) - find_package(CUDAToolkit REQUIRED) - find_library(DDLA_LIBRARY NAMES ddla PATHS "${DDLA_ROOT}/lib" REQUIRED NO_DEFAULT_PATH) + find_package(LibDDLA 0.0.6 REQUIRED CONFIG PATHS + "${DDLA_ROOT}/lib/cmake/LibDDLA" "${DDLA_ROOT}/lib64/cmake/LibDDLA" + NO_DEFAULT_PATH) target_compile_features(test_lri_gpu_symmetry PRIVATE cxx_std_17) target_compile_definitions(test_lri_gpu_symmetry PRIVATE __GPU_RI __DDLA_RI DDLA_USE_CUDA) - target_include_directories(test_lri_gpu_symmetry PRIVATE "${DDLA_ROOT}/include") - target_link_libraries(test_lri_gpu_symmetry PRIVATE - ${DDLA_LIBRARY} CUDA::cudart CUDA::cublas CUDA::curand CUDA::cusolver) + target_link_libraries(test_lri_gpu_symmetry PRIVATE ddla::ddla) endif() enable_testing() diff --git a/unittests/gpu_symmetry/README.md b/unittests/gpu_symmetry/README.md index 167f271..12dba13 100644 --- a/unittests/gpu_symmetry/README.md +++ b/unittests/gpu_symmetry/README.md @@ -14,7 +14,9 @@ cmake --build build-symmetry --parallel 2 ctest --test-dir build-symmetry --output-on-failure ``` -The GPU test requires one GPU, one MPI rank, and DDLA built for CUDA. Omit +The GPU test requires one GPU, one MPI rank, and LibDDLA 0.0.6 or newer built for CUDA. The DDLA package is discovered in +either `lib/cmake/LibDDLA` or `lib64/cmake/LibDDLA`; only its public headers +and imported CMake target are used. Omit `ENABLE_GPU` and `DDLA_ROOT` to check a CPU-only build. The library headers can be selected independently with `LIBRI_ROOT`, allowing the same test to reproduce failures in an earlier revision.