我的程序遇到了一个非常奇怪的问题。基本上我在矩阵的一部分上进行矩阵乘法。该程序显然在大多数卡片上运行良好,但在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错误。
具体地说,在以下卡片上试过了:
我使用了许多具有不同发行版的Linux机器,其中一些使用CUDA 5.5,一些使用CUDA 6.0。至少在我直接控制的机器上,所有卡都使用331 nvidia驱动器系列。
这里有几点需要注意:
此时我非常绝望。我不明白为什么或在哪里我做错了什么。如果有人能帮助我,我真的很感激。
编辑:正如评论中指出的那样,显然它只能在sm_35(即GK110卡)上运行,但在sm_30开普勒卡上运行正常。