CUDA程序在sm_35开普勒GPU上提供cudaErrorIllegalAddress,但在其他GPU上运行良好

CUDA程序在sm_35开普勒GPU上提供cudaErrorIllegalAddress,但在其他GPU上运行良好,c,cuda,pycuda,cublas,C,Cuda,Pycuda,Cublas,我的程序有一个很奇怪的问题。基本上我是在矩阵的一部分上进行矩阵乘法。该程序显然在大多数卡片上运行良好,但在sm_35开普勒(=GK110)卡片上崩溃 最初的程序是用PyCUDA编写的,但后来我设法将其归结为以下用C编写的最小示例: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <cuda.h> #include <cuda_runtime.h> #

我的程序有一个很奇怪的问题。基本上我是在矩阵的一部分上进行矩阵乘法。该程序显然在大多数卡片上运行良好,但在sm_35开普勒(=GK110)卡片上崩溃

最初的程序是用PyCUDA编写的,但后来我设法将其归结为以下用C编写的最小示例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <cublas_v2.h>

int main(int argc, char **argv)
{
    cudaError_t status;
    cublasStatus_t status_blas;
    CUresult status_drv;
    float *A = 0;
    float *B = 0;
    float *C = 0;
    float alpha = 1.0f;
    float beta = 0.0f;
    float *oldA, *oldB, *oldC;
    cublasHandle_t handle;
    int n = 131;
    int m = 2483;
    int k = 3;
    int i;
    CUcontext ctx;

    cuInit(0);
    status_drv = cuCtxCreate(&ctx, 0, 0);
    if (status_drv != CUDA_SUCCESS) {
        fprintf(stderr, "!!!! Context creation error: %d\n", status);
        return EXIT_FAILURE;
    }
    status_blas = cublasCreate(&handle);
    if (status_blas != CUBLAS_STATUS_SUCCESS) {
        fprintf(stderr, "!!!! CUBLAS initialization error\n");
        return EXIT_FAILURE;
    }

    for (i = 0; i < 5; ++i) {
        printf("Iteration %d\n", i);
        if (cudaMalloc((void **)&B, m * k * sizeof(B[0])) != cudaSuccess) {
            fprintf(stderr, "!!!! allocation error (allocate B)\n");
            return EXIT_FAILURE;
        }
        if (cudaMalloc((void **)&C, m * m * sizeof(C[0])) != cudaSuccess) {
            fprintf(stderr, "!!!! allocation error (allocate C)\n");
            return EXIT_FAILURE;
        }
        if (cudaMalloc((void **)&A, n * m * sizeof(A[0])) != cudaSuccess) {
            fprintf(stderr, "!!!! allocation error (allocate A)\n");
            return EXIT_FAILURE;
        }
        int s = 3;
        float * A_slice = A + 128*m;
        status_blas = cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, m, m, s,
            &alpha, A_slice, m, B, k, &beta, C, m);
        if (status_blas != CUBLAS_STATUS_SUCCESS) {
            fprintf(stderr, "!!!! kernel execution error.\n");
            return EXIT_FAILURE;
        }
        if (i == 0) {
            oldA = A;
            oldB = B;
            oldC = C;
        } else if (i == 1) {
            status = cudaFree(oldA);
            if (status != cudaSuccess) {
                fprintf(stderr, "!!!! allocation error (free A, %d)\n", status);
                return EXIT_FAILURE;
            }
            if (cudaFree(oldB) != cudaSuccess) {
                fprintf(stderr, "!!!! allocation error (free B)\n");
                return EXIT_FAILURE;
            }
            if (cudaFree(oldC) != cudaSuccess) {
                fprintf(stderr, "!!!! allocation error (free C)\n");
                return EXIT_FAILURE;
            }
        }
    }
    cublasDestroy(handle);
    cuCtxDestroy(ctx);
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
int main(int argc,字符**argv)
{
错误状态;
古巴国家地位;
治疗结果状态\u drv;
浮点数*A=0;
浮点数*B=0;
浮点数*C=0;
浮动α=1.0f;
浮动β=0.0f;
浮动*oldA、*oldB、*oldC;
立方手柄;
int n=131;
int m=2483;
int k=3;
int i;
CUcontext ctx;
cuInit(0);
状态_drv=cuCtxCreate(&ctx,0,0);
if(状态=CUDA\U成功){
fprintf(stderr,“!!!!上下文创建错误:%d\n”,状态);
返回退出失败;
}
状态_blas=cublasCreate(&handle);
如果(状态为blas!=CUBLAS状态为SUCCESS){
fprintf(stderr,“!!!!CUBLAS初始化错误\n”);
返回退出失败;
}
对于(i=0;i<5;++i){
printf(“迭代%d\n”,i);
if(cudamaloc((void**)和B,m*k*sizeof(B[0])!=cudaSuccess){
fprintf(stderr,“!!!!分配错误(分配B)\n”);
返回退出失败;
}
if(cudamaloc((void**)和C,m*m*sizeof(C[0])!=cudaSuccess){
fprintf(stderr,“!!!!分配错误(分配C)\n”);
返回退出失败;
}
if(cudamaloc((void**)和A,n*m*sizeof(A[0])!=cudaSuccess){
fprintf(stderr,“!!!!分配错误(分配A)\n”);
返回退出失败;
}
int s=3;
浮动*A_切片=A+128*m;
状态=cubllassemm(手柄,CUBLAS_OP_N,CUBLAS_OP_N,m,m,s,
&α,A_切片,m,B,k和β,C,m);
如果(状态为blas!=CUBLAS状态为SUCCESS){
fprintf(stderr,“!!!!内核执行错误。\n”);
返回退出失败;
}
如果(i==0){
oldA=A;
oldB=B;
oldC=C;
}else如果(i==1){
状态=cudaFree(oldA);
如果(状态!=cudaSuccess){
fprintf(stderr,“!!!!分配错误(自由A,%d)\n)”,状态;
返回退出失败;
}
if(cudaFree(oldB)!=cudaSuccess){
fprintf(stderr,“!!!!分配错误(免费B)\n”);
返回退出失败;
}
if(cudaFree(oldC)!=cudaSuccess){
fprintf(stderr,“!!!!分配错误(免费C)\n”);
返回退出失败;
}
}
}
立方体(把手);
cuCtxDestroy(ctx);
返回0;
}
我只在for循环的第二次迭代中释放内存,以模拟原始python程序的行为。当程序试图释放“A”时,它将在for循环的第二次迭代中崩溃,cudaFree返回cudaErrorIllegalAddress错误

具体地说,在以下卡片上进行了试验:

  • NVS 5400M->无问题
  • GTX560Ti->无问题
  • 特斯拉S2050->无问题
  • 未知的sm_30卡(见本文评论)->无问题
  • K40c->碰撞
  • GTX 780->碰撞
  • K20m->碰撞
我使用了许多具有不同发行版的Linux机器,其中一些使用CUDA 5.5,另一些使用CUDA 6.0。至少在我直接控制的机器上,所有的卡都使用了331 nvidia驱动程序系列

这里有几点需要注意:

  • malloc调用的顺序很重要。如果我先分配A再分配B,一切都会好起来
  • 数值常数有点重要。对于某些值(例如n=30),不会发生崩溃,而对于其他值,则会发生崩溃
  • free/malloc调用的顺序很重要。如果我在分配内存的同一个迭代中释放内存,一切都会正常工作
在这一点上,我非常绝望。我不明白我为什么或哪里做错了什么。如果有人能帮助我,我将非常感激


编辑:正如评论中所指出的,显然它只能在sm_35(即GK110卡)上运行,但在sm_30开普勒卡上运行良好。

这个问题应该在CUDA 6.5产品发布包中解决,现在可以从下载。

您发布的代码实际上不会编译。驱动程序API和CUBLAS中的枚举类型不可交换。它在我的机器上使用
nvcc test.c-o test-lcublas-lcuda
编译得很好。您遇到了什么错误?啊,现在我明白了,我检查了
cuCtxCreate
调用
CUBLAS\u STATUS\u SUCCESS
。我犯了愚蠢的错误。但是在本例中,这没关系,因为驱动程序API和CUBLAS都将“0”定义为“调用成功”值。我会修正上面的代码正如我所说的,Cubrasstatus_t、CUresult和cudaError_t不是同一类型,不能互换。在我修复了这个问题之后,代码在sm_30开普勒系统上运行时没有出现错误