C++ 无转置的行主数据CUBLAS矩阵乘法

C++ 无转置的行主数据CUBLAS矩阵乘法,c++,cuda,cublas,C++,Cuda,Cublas,我目前正在尝试在我的GPU上使用CUBLAS实现矩阵乘法 它适用于方阵和特定大小的输入,但对于其他输入,最后一行不会返回(并且包含0,因为这是我实现它的方式)。 我假设这是分配或cublasSgemm语法的问题,但我找不到它在哪里 N.B.:如果您不熟悉CUBLAS: 是的,这就是为什么看起来操作是以另一种方式执行的 任何帮助都将不胜感激 守则: 请注意,gpuerchk和cublasErrchk当然与此无关 #包括 #包括 #包括 #包括 std::vector CUDA_mult_MAT(

我目前正在尝试在我的GPU上使用CUBLAS实现矩阵乘法

它适用于方阵和特定大小的输入,但对于其他输入,最后一行不会返回(并且包含0,因为这是我实现它的方式)。

我假设这是分配或
cublasSgemm
语法的问题,但我找不到它在哪里

N.B.:如果您不熟悉CUBLAS: 是的,这就是为什么看起来操作是以另一种方式执行的

任何帮助都将不胜感激


守则: 请注意,
gpuerchk
cublasErrchk
当然与此无关

#包括
#包括
#包括
#包括
std::vector CUDA_mult_MAT(常数std::vector&data_1、常数数据行、常数数据列、,
常量标准::向量和数据(2行,常量数据(2行,常量数据(2列){
立方手柄;
cublasErrchk(cublasCreate&handle));
std::vector result(data_1_rows*data_2_columns);//保存乘法结果的向量
/*----------------------------------------------------------------------------------------------*/
浮点*GPU\U数据\U 1=NULL;
gpuErrchk(cudamaloc((void**)和GPU_data_1,data_1.size()*sizeof(float));//在GPU上分配内存
gpuErrchk(cudaMemcpy(GPU_数据_1,data_1.data(),data_1.size()*sizeof(float),cudamemcpyhostodevice));//将数据从数据_1复制到GPU数据_1
浮点*GPU_数据_2=NULL;
gpuErrchk(cudamaloc((void**)和GPU_data_2,data_2.size()*sizeof(float));//在GPU上分配内存
gpuErrchk(cudaMemcpy(GPU_数据_2,data_2.data(),data_2.size()*sizeof(float),cudamemcpyhostodevice));//将数据从数据_2复制到GPU数据_2
浮点*GPU_结果=NULL;
gpuErrchk(cudamaloc((void**)和GPU_result,result.size()*sizeof(float));//在GPU上分配内存
/*----------------------------------------------------------------------------------------------*/
常数浮点α=1.f;
常数浮点β=0.f;
库布拉塞尔奇克(
cublasSgemm(把手、CUBLAS_OP_N、CUBLAS_OP_N、,
数据列、数据行、数据列、,
&alpha、GPU数据列、数据列、,
GPU_数据_1,数据_1_列,
&测试版、GPU结果、数据(1行)
);//执行乘法
gpuErrchk(cudaMemcpy(result.data(),GPU_result,result.size()*sizeof(float),cudaMemcpyDeviceToHost));//复制回向量“result”
gpuErrchk(cudaFree(GPU_数据_1));//释放GPU内存
gpuErrchk(cudaFree(GPU_data_2));//释放GPU内存
gpuErrchk(cudaFree(GPU_结果));//释放GPU内存
cublasErrchk(cublasDestroy_v2(手柄));
返回结果;
}

输入:

#包括
#包括
int main(){
常数std::向量r1=CUDA_mult_MAT({1,2,3,4,5,6},2,3,
{7 , 8 , 9 , 10 , 11 , 12} , 3 , 2);
/*
产品:
7  8
1 2 3    9  10
4 5 6    11 12
*/

对于(auto&value:r1){std::cout我们可以通过不同的方式观察到CUBLAS的使用问题

首先,通过研究,我们看到三个参数
m
n
k
以该顺序出现在转置说明符之后:

cublasStatus_t cublasSgemm(cublasHandle_t handle,
                       cublasOperation_t transa, cublasOperation_t transb,
                       int m, int n, int k, 
                           ^      ^      ^
我们还观察到,矩阵维数由以下公式给出:

A、B和C是以列主格式存储的矩阵,其维数为op(A)m×k、op(B)k×n和cm×n

因此,第一个输入矩阵的维数为
mxk
第二个输入矩阵的维数为
kxn
,输出矩阵的维数为
mxn

让我们先关注一下输出矩阵。考虑到它的维度是使用
m
n
参数指定的,因此只传递以下维度的
数据_2
维度可能是不正确的(比如在非方形情况下):

           cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
                       data_2_columns , data_2_rows ,data_1_columns,
                       ^^^^^^^^^^^^^^   ^^^^^^^^^^^
其次,从错误检查的角度来看,通过使用
cuda memcheck
运行代码,您可以快速判断CUBLAS调用是否有问题。报告的第一个错误如下:

$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
========= Invalid __global__ read of size 4
=========     at 0x000006f0 in void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>)
=========     by thread (64,0,0) in block (0,0,0)
=========     Address 0x7f9c30a2061c is out of bounds
=========     Device Frame:void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>) (void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>) : 0x6f0)
=========     Saved host backtrace up to driver entry point at kernel launch time
=========     Host Frame:/usr/lib/x86_64-linux-gnu/libcuda.so.1 (cuLaunchKernel + 0x2b8) [0x1e5cc8]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x1063c8b]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x10a9965]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x6bfacc]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x5fc7af]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x436c35]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 (cublasLtMatmul + 0x60f) [0x43484f]
=========     Host Frame:/usr/local/cuda/lib64/libcublas.so.11 [0x9ef6db]
=========     Host Frame:/usr/local/cuda/lib64/libcublas.so.11 [0x50e4f0]
=========     Host Frame:/usr/local/cuda/lib64/libcublas.so.11 (cublasSgemm_v2 + 0x1ee) [0x50f29e]
=========     Host Frame:./t23 [0x7986]
=========     Host Frame:./t23 [0x7b4c]
=========     Host Frame:/lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main + 0xe7) [0x21b97]
=========     Host Frame:./t23 [0x744a]
=========
当我编译并运行带有这些更改的代码时,我得到以下结果:

           cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
                       data_2_columns , data_1_rows ,data_1_columns,
                       &alpha , GPU_data_2 , data_2_columns,
                       GPU_data_1 , data_1_columns,
                       &beta , GPU_result , data_2_columns)
$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
58 64 139 154
39 54 69 49 68 87 59 82 105
========= ERROR SUMMARY: 0 errors

我们可以通过不同的方式观察您的CUBLAS使用问题

首先,通过研究,我们看到三个参数
m
n
k
以该顺序出现在转置说明符之后:

cublasStatus_t cublasSgemm(cublasHandle_t handle,
                       cublasOperation_t transa, cublasOperation_t transb,
                       int m, int n, int k, 
                           ^      ^      ^
我们还观察到,矩阵维数由以下公式给出:

A、B和C是以列主格式存储的矩阵,其维数为op(A)m×k、op(B)k×n和cm×n

因此,第一个输入矩阵的维数为
mxk
第二个输入矩阵的维数为
kxn
,输出矩阵的维数为
mxn

让我们先关注一下输出矩阵。考虑到它的维度是使用
m
n
参数指定的,因此只传递以下维度的
数据_2
维度可能是不正确的(比如在非方形情况下):

           cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
                       data_2_columns , data_2_rows ,data_1_columns,
                       ^^^^^^^^^^^^^^   ^^^^^^^^^^^
其次,从错误检查的角度来看,通过使用
cuda memcheck
运行代码,您可以快速判断CUBLAS调用是否有问题。报告的第一个错误如下:

$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
========= Invalid __global__ read of size 4
=========     at 0x000006f0 in void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>)
=========     by thread (64,0,0) in block (0,0,0)
=========     Address 0x7f9c30a2061c is out of bounds
=========     Device Frame:void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>) (void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>) : 0x6f0)
=========     Saved host backtrace up to driver entry point at kernel launch time
=========     Host Frame:/usr/lib/x86_64-linux-gnu/libcuda.so.1 (cuLaunchKernel + 0x2b8) [0x1e5cc8]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x1063c8b]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x10a9965]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x6bfacc]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x5fc7af]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x436c35]
=========     Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 (cublasLtMatmul + 0x60f) [0x43484f]
=========     Host Frame:/usr/local/cuda/lib64/libcublas.so.11 [0x9ef6db]
=========     Host Frame:/usr/local/cuda/lib64/libcublas.so.11 [0x50e4f0]
=========     Host Frame:/usr/local/cuda/lib64/libcublas.so.11 (cublasSgemm_v2 + 0x1ee) [0x50f29e]
=========     Host Frame:./t23 [0x7986]
=========     Host Frame:./t23 [0x7b4c]
=========     Host Frame:/lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main + 0xe7) [0x21b97]
=========     Host Frame:./t23 [0x744a]
=========
当我编译并运行带有这些更改的代码时,我得到以下结果:

           cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
                       data_2_columns , data_1_rows ,data_1_columns,
                       &alpha , GPU_data_2 , data_2_columns,
                       GPU_data_1 , data_1_columns,
                       &beta , GPU_result , data_2_columns)
$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
58 64 139 154
39 54 69 49 68 87 59 82 105
========= ERROR SUMMARY: 0 errors

非常感谢。我不敢相信我错过了这样一个错误。我也要感谢你一直以来为你的启发性答案付出的努力。能够从他们身上学到很多东西令人难以置信的满足。非常感谢。我不敢相信我错过了