2014-07-10 6 views
3

У меня очень странная проблема с моей программой. По существу, я делаю умножение матрицы на часть матрицы. Очевидно, что программа работает нормально на большинстве карт, но падает на карты sm_35 Kepler (= GK110).Программа CUDA дает cudaErrorIllegalAddress на графических процессорах sm_35 Kepler, но работает на отлично на других графических процессорах

Первоначальная программа была написана в 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; 
} 

Я только свободной памяти на 2-й итерации для цикла для имитации поведения исходной программы python. Программа выйдет из строя во второй итерации цикла for, когда попытается освободить «A», cudaFree вернет ошибку cudaErrorIllegalAddress.

Конкретно, не апробировано на следующие карты:

  • NVS 5400м -> нет проблем
  • GTX560Ti -> никаких вопросов
  • Tesla S2050 -> никаких вопросов
  • неизвестно sm_30 карты (не вижу комментарии на этот пост) -> нет проблем
  • K40c -> CRASH
  • GTX 780 -> CRASH
  • K20m -> CRASH

Я использовал ряд машин Linux с различными дистрибутивами, некоторые из которых используют CUDA 5.5 и некоторые используют CUDA 6.0. По крайней мере, на машинах, которыми я управлял, все карты использовали 331 драйвер nvidia.

Есть несколько вещей, чтобы отметить здесь:

  • порядок таНоса называют вопросы. Если я распределю A до того, как B все будет нормально работать
  • Численные константы имеют значение. Для некоторых значений (например, n = 30) авария не возникает, для других возникает сбой
  • Порядок вызова free/malloc. Если я освобожу память на той же самой итерации, где я выделил, все работает просто отлично

На данный момент я довольно отчаянный. Я не понимаю, почему и где я делаю что-то неправильно. Если бы кто-нибудь мог мне помочь, я бы очень признателен.

EDIT: как указано в комментариях, по-видимому, он не работает только на sm_35 (то есть карты GK110), но отлично работает на картах Kepler sm_30.

+0

код, который вы выложили не компилировать. Перечисленные типы из API-интерфейса драйвера и CUBLAS не взаимозаменяемы. – talonmies

+0

Он отлично компилируется на моей машине, используя 'nvcc test.c -o test -lcublas -lcuda'. Какую ошибку вы получаете? – Untom

+0

А теперь, я вижу, я проверил вызов 'cuCtxCreate' для' CUBLAS_STATUS_SUCCESS'. Глупая ошибка с моей стороны. Однако в этом случае это нормально, так как API-интерфейс драйвера и CUBLAS определяют «0» как их «успешный вызов». Я исправлю код выше. – Untom

ответ

3

Эта проблема должна быть решена в пакете выпуска 6,5 производства CUDA, теперь доступен для загрузки с http://www.nvidia.com/getcuda

 Смежные вопросы

  • Нет связанных вопросов^_^