2015-10-21 5 views
0

При попытке выполнить тензор-произведение матриц с помощью cublasSgemm подпрограмму, адрес из границ возникновения ошибок, пример которого приведен ниже: -cublasSgemm недействительным __global__ чтения

========= Invalid __global__ read of size 4 
=========  at 0x000019f8 in sgemm_sm35_ldg_nn_64x16x64x16x16 
=========  by thread (6,3,0) in block (6,3,0) 
=========  Address 0x7ffc059064a8 is out of bounds 
=========  Saved host backtrace up to driver entry point at kernel launch time 
=========  Host Frame:/lib64/libcuda.so.1 (cuLaunchKernel + 0x2cd) [0x15859d] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0x21fb31] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0x23a343] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0x1d4e92] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0x1d17b4] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0x1d2c5e] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0x1d37b2] 
=========  Host Frame:/usr/local/cuda-7.5/lib64/libcublas.so.7.5 [0xecd31] 
=========  Host Frame:./test [0x2c0e] 
=========  Host Frame:./test [0x2a99] 
=========  Host Frame:/lib64/libc.so.6 (__libc_start_main + 0xf5) [0x21af5] 
=========  Host Frame:./test [0x2749] 

После проверки Размеры несколько раз в мое приложение и определение того, что это не проблема, я написал минимальный рабочий пример. Ниже приведен простой пример, который умножает две квадратных матриц: -

#include "stdlib.h" 
#include "time.h" 
#include "stdio.h" 
#include "cuda.h" 
#include <cuda_runtime.h> 
#include "cublas_v2.h" 
#include <math.h> 
#include "cuda_error.h" 

void matrixMult(cublasOperation_t transA, cublasOperation_t transB, int M, int N, 
      int K, float alpha, float *A, float *B, float beta, float *C, 
       cublasHandle_t *cb_handle); 

int main(){ 
    int i, j, idx; 
    int D = 500; 

    int len = D*D; 
    float *A_h, *B_h, *C_h; 
    float *A_d, *B_d, *C_d; 

    A_h = (float*)malloc(len*sizeof(float)); 
    B_h = (float*)malloc(len*sizeof(float)); 
    C_h = (float*)malloc(len*sizeof(float)); 

    srand48(time(NULL)); 
    for(i=0; i<D; i++){ 
     for(j=0; j<D; j++){ 
      A_h[i*D + j] = drand48(); 
      B_h[i*D + j] = drand48(); 
     } 
    } 

    cudaCheck(cudaMalloc((void**)&A_d, len*sizeof(float))); 
    cudaCheck(cudaMalloc((void**)&B_d, len*sizeof(float))); 
    cudaCheck(cudaMalloc((void**)&C_d, len*sizeof(float))); 
    cudaCheck(cudaMemcpy(A_d, A_h, len*sizeof(float), cudaMemcpyHostToDevice)); 
    cudaCheck(cudaMemcpy(B_d, B_h, len*sizeof(float), cudaMemcpyHostToDevice)); 

    cublasHandle_t cb_handle; 
    cublasCheck(cublasCreate(&cb_handle)); 
    cublasSetPointerMode(cb_handle, CUBLAS_POINTER_MODE_DEVICE); 
    matrixMult(CUBLAS_OP_N, CUBLAS_OP_N, D, D, D, 1.0, B_d, A_d, 0.0, C_d, &cb_handle); 
    cublasDestroy(cb_handle); 

    cudaCheck(cudaMemcpy(C_h, C_d, len*sizeof(float), cudaMemcpyDeviceToHost)); 
    cudaCheck(cudaFree(A_d)); 
    cudaCheck(cudaFree(B_d)); 
    cudaCheck(cudaFree(C_d)); 

    free(A_h); 
    free(B_h); 
    free(C_h); 
} 

void matrixMult(cublasOperation_t transA, cublasOperation_t transB, int M, int N, 
      int K, float alpha, float *A, float *B, float beta, float *C, 
      cublasHandle_t *cb_handle){ 
    int lda = (transA == CUBLAS_OP_N) ? K : M; 
    int ldb = (transB == CUBLAS_OP_N) ? N : K; 
    int ldc = N; 
    cublasCheck(cublasSgemm(*cb_handle, transB, transA, N, M, K, &alpha, B, ldb, A, lda, &beta, C, ldc)); 
} 

со следующим заголовком захвата тривиальной ошибки: -

#ifndef CUDA_ERROR_CHECK 
#define CUDA_ERROR_CHECK 

#include <cuda_runtime.h> 
#include "cublas_v2.h" 

#define cudaCheck(ans){cuda_assert((ans), __FILE__, __LINE__);} 
#define cublasCheck(ans){cublas_assert((ans), __FILE__, __LINE__);} 

inline void cuda_assert(cudaError_t code, const char *file, int line){ 
    if(code != cudaSuccess){ 
     fprintf(stderr,"CUDA Error: %s %s %d\n", cudaGetErrorString(code), file, line); 
     exit(code); 
    } 
} 

inline void cublas_assert(cublasStatus_t code, const char *file, int line){ 
    if(code != CUBLAS_STATUS_SUCCESS){ 
     fprintf(stderr, "CUBLAS Error! %s line: %d error code: %d\n", file, line, code); 
     exit(code); 
    } 
} 

#endif 

Обратите внимание, что выше вывод ошибок производились с помощью приведенного выше квадратного примере матрицы. Аналогичный выход получается для моего приложения тензорного продукта.

Я использую CUDA 7.5 с картой Titan Black. Я делаю что-то принципиально неправильное, или это может быть проблемой с моей установкой cuBLAS?

ответ

1

Если устранить это:

cublasSetPointerMode(cb_handle, CUBLAS_POINTER_MODE_DEVICE); 

ваш код будет работать без ошибок. Непонятно, почему вы устанавливаете режим указателя на CUBLAS_POINTER_MODE_DEVICE. documentation указывает:

Есть две категории функций, которые используют скалярные параметры:

  • функции, которые принимают альфа и/или бета-параметров по ссылке на хосте или устройства в качестве коэффициентов масштабирования, таких как gemm

  • функции, которые возвращают скалярный результат на хост или устройство, такие как amax(), amin, asum(), rotg(), rotmg(), dot() и nrm2().

Для функций первой категории, когда режим указателя установлен в CUBLAS_POINTER_MODE_HOST, скалярные параметры альфа и/или бета может быть в стеке или в куче.

CUBLAS_POINTER_MODE_HOST является настройка по умолчанию , и это правильная установка в вашем случае, когда &alpha и &beta являются указателями на хост-память:

cublasCheck(cublasSgemm(*cb_handle, transB, transA, N, M, K, &alpha, B, ldb, A, lda, &beta, C, ldc)); 
+0

О, дорогая! Я думаю, что я запутался в том, что делает эта функция, думая, что это правильно для моего случая использования, поэтому не подумал дважды проверить это. Благодарю. –

+0

Оказалось, что это возможная причина. –