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

时间:2014-07-10 08:31:56

标签: c cuda pycuda cublas

我的程序遇到了一个非常奇怪的问题。基本上我在矩阵的一部分上进行矩阵乘法。该程序显然在大多数卡片上运行良好,但在sm_35 Kepler(= 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;
}

我只在for循环的第二次迭代中释放内存来模仿原始python程序的行为。当程序尝试释放“A”时,程序将在for循环的第二次迭代中崩溃,cudaFree返回cudaErrorIllegalAddress错误。

具体地说,在以下卡片上试过了:

  • NVS 5400M - &gt;没问题
  • GTX560Ti - &gt;没问题
  • 特斯拉S2050 - &gt;没问题
  • 未知sm_30卡(见本帖评论) - &gt;没问题
  • K40c - &gt; CRASH
  • GTX 780 - &gt; CRASH
  • K20m - &gt; CRASH

我使用了许多具有不同发行版的Linux机器,其中一些使用CUDA 5.5,一些使用CUDA 6.0。至少在我直接控制的机器上,所有卡都使用331 nvidia驱动器系列。

这里有几点需要注意:

  • malloc调用的顺序很重要。如果我在B之前分配A,那么运行正常
  • 数值常数有点重要。对于某些值(例如,n = 30),不会发生崩溃,而其他值则会发生崩溃
  • free / malloc调用的顺序很重要。如果我在我分配的同一次迭代中释放内存,一切正常

此时我非常绝望。我不明白为什么或在哪里我做错了什么。如果有人能帮助我,我真的很感激。

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

1 个答案:

答案 0 :(得分:3)

此问题应在CUDA 6.5生产发布包中修复,现在可从http://www.nvidia.com/getcuda下载