2015-01-13 4 views
4

Я пытаюсь использовать cublas функцию cublasSgemmBatched в моем примере игрушки. В этом примере я сначала выделяю двумерные массивы: h_AA, h_BB размера [6] [] и h_CC размера [6] [1]. После этого я скопировал его на устройство, выполнив cublasSgemmBatched и попытался скопировать массив d_CC обратно в массив хоста h_CC. Тем не менее, я получил ошибку (cudaErrorLaunchFailure) с устройством для размещения копирования и я не уверен, что я скопировал массивы в устройство правильно:Копирование массива указателей в память устройства и обратно (CUDA)

int main(){ 
    cublasHandle_t handle; 
    cudaError_t cudaerr; 
    cudaEvent_t start, stop; 
    cublasStatus_t stat; 
    const float alpha = 1.0f; 
    const float beta = 0.0f; 
    float **h_AA, **h_BB, **h_CC; 
    h_AA = new float*[6]; 
    h_BB = new float*[6]; 
    h_CC = new float*[6]; 
    for (int i = 0; i < 6; i++){ 
     h_AA[i] = new float[5]; 
     h_BB[i] = new float[5]; 
     h_CC[i] = new float[1]; 
     for (int j = 0; j < 5; j++){ 
      h_AA[i][j] = j; 
      h_BB[i][j] = j; 
     } 
     h_CC[i][0] = 1; 
    } 
    float **d_AA, **d_BB, **d_CC; 
    cudaMalloc(&d_AA, 6 * sizeof(float*)); 
    cudaMalloc(&d_BB, 6 * sizeof(float*)); 
    cudaMalloc(&d_CC, 6 * sizeof(float*)); 
    cudaerr = cudaMemcpy(d_AA, h_AA, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
    cudaerr = cudaMemcpy(d_BB, h_BB, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
    cudaerr = cudaMemcpy(d_CC, h_CC, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
    stat = cublasCreate(&handle); 
    stat = cublasSgemmBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N, 1, 1, 5, &alpha, 
      (const float**)d_AA, 1, (const float**)d_BB, 5, &beta, d_CC, 1, 6); 
    cudaerr = cudaMemcpy(h_CC, d_CC, 6 * sizeof(float*), cudaMemcpyDeviceToHost); 
    cublasDestroy(handle); 
} 

Так что этот код работает, однако последний cudaerr возвращается cudaErrorLaunchFailure. Я пытался следовать этому образцу кода на Github.

P.S. Что я не понимаю, что такое sizeof(float*) и как cudaMalloc знает, сколько памяти требуется для каждого массива (например, здесь я определяю только размер 1).

UPDATE: Я сделал это !!:

cublasHandle_t handle; 
cudaError_t cudaerr; 
cudaEvent_t start, stop; 
cublasStatus_t stat; 
const float alpha = 1.0f; 
const float beta = 0.0f; 

float *h_A = new float[5]; 
float *h_B = new float[5]; 
float *h_C = new float[6]; 
for (int i = 0; i < 5; i++) 
{ 
    h_A[i] = i; 
    h_B[i] = i; 
} 



float **h_AA, **h_BB, **h_CC; 
h_AA = (float**)malloc(6* sizeof(float*)); 
h_BB = (float**)malloc(6 * sizeof(float*)); 
h_CC = (float**)malloc(6 * sizeof(float*)); 
for (int i = 0; i < 6; i++){ 
    cudaMalloc((void **)&h_AA[i], 5 * sizeof(float)); 
    cudaMalloc((void **)&h_BB[i], 5 * sizeof(float)); 
    cudaMalloc((void **)&h_CC[i], sizeof(float)); 
    cudaMemcpy(h_AA[i], h_A, 5 * sizeof(float), cudaMemcpyHostToDevice); 
    cudaMemcpy(h_BB[i], h_B, 5 * sizeof(float), cudaMemcpyHostToDevice); 
} 
float **d_AA, **d_BB, **d_CC; 
cudaMalloc(&d_AA, 6 * sizeof(float*)); 
cudaMalloc(&d_BB, 6 * sizeof(float*)); 
cudaMalloc(&d_CC, 6 * sizeof(float*)); 
cudaerr = cudaMemcpy(d_AA, h_AA, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
cudaerr = cudaMemcpy(d_BB, h_BB, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
cudaerr = cudaMemcpy(d_CC, h_CC, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
stat = cublasCreate(&handle); 
    stat = cublasSgemmBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N, 1, 1, 5, &alpha, 
      (const float**)d_AA, 1, (const float**)d_BB, 5, &beta, d_CC, 1, 6); 
    cudaerr = cudaMemcpy(h_CC, d_CC, sizeof(float), cudaMemcpyDeviceToHost); 
    for (int i = 0; i < 6;i++) 
     cudaMemcpy(h_C+i, h_CC[i], sizeof(float), cudaMemcpyDeviceToHost); 
cublasDestroy(handle); 
+0

Перепутанные данные, которые вы передаете, вызывают одно из ядер, запускаемых при вызове группового гемма. Как асинхронная ошибка, вы не можете получать уведомление об этом до следующего вызова cuda. Изучали ли вы пакетные кубы [образец кода cuda] (http://docs.nvidia.com/cuda/cuda-samples/index.html#batchcublas)? –

+0

Я этого не делал сейчас –

+0

Я сделал это! Благодарю. Итак, правильно ли я понимаю: для того, чтобы иметь дело с двумерными массивами устройств, вы должны создать массив узлов указателей на массивы устройств и после этого скопировать этот массив в память массива 2D-устройств. Чтобы получить массив 2D-хоста из массива 2D-устройств, вы должны снова использовать промежуточный 2D-массив, который представляет собой массив указателей узлов на массивы устройств. Я опубликовал рабочий код в Update –

ответ

5

Итак, я понял, ответ (спасибо @Robert Crovella): для того, чтобы создать device array of pointers to device arrays (для пакетных функций), необходимо сначала создать host array of pointers to device arrays , и после этого скопируйте его в device array of pointers to device arrays. То же самое касается перевода обратно на хост: нужно использовать промежуточный host array of pointers to device arrays.

cublasHandle_t handle; 
cudaError_t cudaerr; 
cudaEvent_t start, stop; 
cublasStatus_t stat; 
const float alpha = 1.0f; 
const float beta = 0.0f; 

float *h_A = new float[5]; 
float *h_B = new float[5]; 
float *h_C = new float[6]; 
for (int i = 0; i < 5; i++) 
{ 
    h_A[i] = i; 
    h_B[i] = i; 
} 



float **h_AA, **h_BB, **h_CC; 
h_AA = (float**)malloc(6* sizeof(float*)); 
h_BB = (float**)malloc(6 * sizeof(float*)); 
h_CC = (float**)malloc(6 * sizeof(float*)); 
for (int i = 0; i < 6; i++){ 
    cudaMalloc((void **)&h_AA[i], 5 * sizeof(float)); 
    cudaMalloc((void **)&h_BB[i], 5 * sizeof(float)); 
    cudaMalloc((void **)&h_CC[i], sizeof(float)); 
    cudaMemcpy(h_AA[i], h_A, 5 * sizeof(float), cudaMemcpyHostToDevice); 
    cudaMemcpy(h_BB[i], h_B, 5 * sizeof(float), cudaMemcpyHostToDevice); 
} 
float **d_AA, **d_BB, **d_CC; 
cudaMalloc(&d_AA, 6 * sizeof(float*)); 
cudaMalloc(&d_BB, 6 * sizeof(float*)); 
cudaMalloc(&d_CC, 6 * sizeof(float*)); 
cudaerr = cudaMemcpy(d_AA, h_AA, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
cudaerr = cudaMemcpy(d_BB, h_BB, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
cudaerr = cudaMemcpy(d_CC, h_CC, 6 * sizeof(float*), cudaMemcpyHostToDevice); 
stat = cublasCreate(&handle); 
    stat = cublasSgemmBatched(handle, CUBLAS_OP_N, CUBLAS_OP_N, 1, 1, 5, &alpha, 
      (const float**)d_AA, 1, (const float**)d_BB, 5, &beta, d_CC, 1, 6); 
    cudaerr = cudaMemcpy(h_CC, d_CC, sizeof(float), cudaMemcpyDeviceToHost); 
    for (int i = 0; i < 6;i++) 
     cudaMemcpy(h_C+i, h_CC[i], sizeof(float), cudaMemcpyDeviceToHost); 
cublasDestroy(handle);