c - cublas 矩阵矩阵乘法在应用于具有多个 GPU 的一个非常长的维度的矩阵时会产生内部错误
问题描述
我试图做的是简单地将 cublasDgemm(矩阵-矩阵乘法)应用于具有“双”(8 字节)类型元素的几个矩阵,所有这些矩阵都有一个非常大的维度。在我的例子中,矩阵的大小是 12755046 x 46。简单地说,A[46,12755046]*B_i[12755046,46] = C_i[46,46],其中 i = 1,2,3,... .
该机器包括 128GB 内存和两个 GTX2080Ti(11GB GPU 内存),所以我最初的策略是将 B_i 分配给每个 GPU。但是,当我在两个 GPU 上执行我的代码时,我总是会收到 INTERNAL ERROR。
所以我通过尝试三件事解决了这个问题: 1. 只使用一个 GPU。没有错误。2. 缩小矩阵大小,但继续使用两个 GPU。没有错误。3. 使用隐式使用两个 GPU 的 cublasXt。没有错误。
虽然解决了,但我仍然有兴趣找到为什么我的原始计划不适用于大维矩阵的答案?我猜这可能是由于 cublas 的一些内部限制或者我错过了一些配置?
我在这里附上了我的简化代码来说明我的原始计划:
double *A, *B[2], *C[2];
cudaMallocManaged(&A, 46*12755046*sizeof(double));
cudaMallocManaged(&B[0], 46*12755046*sizeof(double));
cudaMallocManaged(&B[1], 46*12755046*sizeof(double));
cudaMallocManaged(&C[0], 46*12755046*sizeof(double));
cudaMallocManaged(&C[1], 46*12755046*sizeof(double));
givevalueto(A);
givevalueto(B[0]);
givevalueto(B[1]);
double alpha = 1.0;
double beta = 0.0;
cublasHandle_t handle[nGPUs];
int iGPU;
for(iGPU=0;iGPU<nGPUs;iGPU++)
{
cublasCreate (& handle[iGPU]);
}
for(iGPU=0;iGPU<nGPUs;i++)
{
cudaSetDevice(iGPU);
cublasDgemm(handle[iGPU],CUBLAS_OP_N,CUBLAS_OP_N,46,46,12755046,&alpha,A,46,B[iGPU],12755046,&beta,C[iGPU],46);
}
for(iGPU=0;iGPU<nGPUs;i++)
{
cudaSetDevice(iGPU);
cudaDeviceSynchronize();
}
for(iGPU=0;iGPU<nGPUs;iGPU++)
{
cudaFree(B[iGPU]);
}
解决方案
cublas 句柄适用于创建句柄时处于活动状态的设备。
从文档中cublasCreate
:
CUBLAS 库上下文与当前的 CUDA 设备相关联。
另见cublas 上下文的描述:
假定与特定 cuBLAS 上下文关联的设备在相应的 cublasCreate() 和 cublasDestroy() 调用之间保持不变。为了使 cuBLAS 库在同一主机线程中使用不同的设备,应用程序必须通过调用 cudaSetDevice() 设置要使用的新设备,然后通过调用创建另一个与新设备关联的 cuBLAS 上下文cublasCreate()。
您可以使用以下方法修复您的代码:
for(iGPU=0;iGPU<nGPUs;iGPU++)
{
cudaSetDevice(iGPU); // add this line
cublasCreate (& handle[iGPU]);
}
推荐阅读
- javascript - 读取多个文件并写入一个文件 Node.JS
- asp.net-core - 为什么没有应用api版本?
- groovy - JMeter - 在 HTTP 采样器中访问 JSR223 变量
- linux - 在文件中打印指定数量的行直到结束
- python - Minimax 与 alhpa-beta 修剪的国际象棋
- python - 如何从多对多关系中检索条目
- pervasive - Btrieve 文件只显示部分数据
- karate - 空手道是否支持 WebSocket 延续帧?
- java - 在这种情况下如何扩展自定义布局并编辑您的视图?
- laravel - 在laravel 6.0中计算各种列的元素