使用 cublas gemm 函数 (cublasSgemm) 的乘法矩阵大小上限

Posted

技术标签:

【中文标题】使用 cublas gemm 函数 (cublasSgemm) 的乘法矩阵大小上限【英文标题】:Upper Limit on Matrix Size for Multiplication using cublas gemm function (cublasSgemm) 【发布时间】:2016-03-31 09:59:24 【问题描述】:

这是我第一次无法从以前发布的问题的答案中获得帮助。

我一直在使用 cublasSgemm 非常成功地乘方矩阵。 但是,最近我观察到,如果行数或列数增加超过 269(即 270 x 270 矩阵及以上),当我 调试时,我开始得到“内存访问冲突”启用 Nsight Cuda 内存检查器。如果我不启用内存检查器,则没有异常,结果也是正确的。

以下是确切的错误消息

内存检查器检测到 64 次访问冲突

存储(全局内存)访问冲突

这是我的 gpu 或 cublasSgemm 功能的限制吗? 我该怎么做才能解决这个问题?

我在 Quadro FX 1800M (sm_12) 上使用带有 MS Visual Studio 2012 的 Cuda 6.5。操作系统是 MS Windows 7 64 位。

我在下面包含了一个精简版的代码

#include <stdio.h>
#include <cuda.h>
#include <cublas_v2.h>

int main(int argc, char **argv)

const int m = 269; // for 1 - 269 there are no access violations
// but as soon as m >= 270 Memory Checker throws memory access violations
// Note: the results are correct even with these violations
float *X = new float[m*m];
float *Y = new float[m*m];
float *Z = new float[m*m];
float *devX, *devY, *devZ;
cublasHandle_t handle;
cudaError_t err;
cublasStatus_t err1;

//simple initialization
for(unsigned long i = 0; i < m*m; i++)

    X[i] = 1;
    Y[i] = 2;


err1 = cublasCreate(&handle);
if(err1 != CUBLAS_STATUS_SUCCESS)
  return 1;

err = cudaMalloc((void **)&devX, m*m*sizeof(*devX));
if(err != CUBLAS_STATUS_SUCCESS)
  return 1;

err = cudaMalloc((void **)&devY, m*m*sizeof(*devY));
if(err != CUBLAS_STATUS_SUCCESS)
  return 1;

err = cudaMalloc((void **)&devZ, m*m*sizeof(*devZ));
if(err != CUBLAS_STATUS_SUCCESS)
  return 1;


err1 = cublasSetMatrix(m, m, sizeof(*X), X, m, devX, m);
if(err1 != CUBLAS_STATUS_SUCCESS)
  return 1;

err1 = cublasSetMatrix(m, m, sizeof(*Y), Y, m, devY, m);
if(err1 != CUBLAS_STATUS_SUCCESS)
  return 1;

////////////////////////////////////////////////////////////
printf("Reached sgemm without error\n");
const float alpha = 1.0f, beta = 0.0f;
// cuda memory checker detects access violations when m > 269
cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, m, m, &alpha, devX, m, devY, m, &beta, devZ, m);
cudaDeviceSynchronize();
printf("reached after sgemm without error\n");
////////////////////////////////////////////////////////////

err1 = cublasGetMatrix(m, m, sizeof(*devZ), devZ, m, Z, m);
if(err != CUBLAS_STATUS_SUCCESS)
  return 1;

// just printing a single element for brevity
printf("....%f....", Z[0]); 

cudaFree(devX);
cudaFree(devY);
cudaFree(devZ);
cublasDestroy_v2(handle);
getchar();
return 0;

已编辑

Update: Same result even after disabling TDR, as shown in this image

再次编辑

编译并运行从以下网站下载的 cublas 示例:

https://people.maths.ox.ac.uk/gilesm/cuda/prac5/simpleCUBLAS.cpp

再次为 N > 500 得到与以前相同的错误。

如果 Cuda Memory Checker 未启用,则该程序会像之前一样成功运行并显示“测试通过”消息。

实际上,访问违规从 N = 350 开始,但此时它们是不可预测的,即它们有时会发生,而有时它们不会发生。但是对于 N > 500,它们总是会出现

使用 cudaDeviceGetLimit(&heap_size, cudaLimitMallocHeapSize);获得 3435973836 字节的 heap_size。所以,大概这也不是问题!

已编辑 我现在已经在“C:\ProgramData\NVIDIA Corporation\CUDA Samples\v6.5\7_CUDALibraries\simpleCUBLAS”运行示例项目代码。不走运!!

已编辑可能是使用单个 GPU 的原因吗?

【问题讨论】:

还要注意的是,为两个输入矩阵和一个输出矩阵分配内存是没有问题的。 GPU 的内存为 1GB。 存在错误检测之类的东西。你确定这些是真的吗?你能自己检测到它们吗?这还重要吗? 您可能遇到了 Windows TDR 事件。您是否修改过 TDR 超时设置? 我已经在 Windows 中的 Quadro FX1800 上的 CUDA 6.5 上运行了您的代码,但没有发现任何内存检查器问题。你能正确运行 simpleCUBLAS [示例代码]()(有或没有内存检查器)吗?那是在做一个 320x320 的 sgemm 操作。 @RobertCrovella:我尝试过禁用 TDR,甚至将其增加到 60 秒的高值 【参考方案1】:

尽管以下不是一个“完整”的答案,但即便如此我还是决定分享我的观察结果

我终于决定切换回在 linux 上使用 cuda。 使用带有 memcheck 的 cuda-gdb。虽然在级别 1 中运行 linux 并不好玩,但所有与使用 windows 相关的不确定性都被消除了 上面的代码现在可以运行 N = 15000。

简而言之,cublas gemm 函数只受硬件能力的限制

【讨论】:

您不必切换到运行级别 1。如果您的目标是阻止 X 运行,则运行级别 3 应该没问题。 @RobertCrovella 但在我的 ubuntu 14.04 上停止 lightdm 不起作用。所以我只是切换到运行级别 1 您不必停止 lightdm。在运行级别 3 中,X 服务不会在启动时启动。将运行级别设置为 3 并重新启动。运行级别 3 的优点是网络之类的东西仍然可以正常工作,并且您仍然可以将 linux 用作多用户环境。

以上是关于使用 cublas gemm 函数 (cublasSgemm) 的乘法矩阵大小上限的主要内容,如果未能解决你的问题,请参考以下文章

异步 cuBLAS 调用

cublas如何实现异步标量变量传输

cublas 函数调用 cublasSgemv

cublas 函数的重叠输入和输出

CUDA 内核可以调用 cublas 函数吗?

相当于 cuBLAS 的 cudaGetErrorString?