2011-12-24 4 views
0

CUDA + CUBLAS를 사용하여 저의 첫 프로그램을 작성했습니다. 'cublasDgemm'함수를 사용하고 2 개의 N * N 행렬의 곱을 계산합니다.CUBLAS가 예기치 않게 작동합니다

그러나 내 프로그램을 시작할 때마다 동일한 잘못된 대답이 계속 발생했습니다 (예 : 5를 단일 요소로 포함하는 1 * 1 행렬에 요소 6이 포함 된 1 * 1 행렬을 곱하면 결과는 항상 나타남) 30이 아닌 36입니다. 프로그램을 여러 번 확인했지만 성공하지 못했습니다. 하지만, 재부팅 후 nexy day로 돌아 왔을 때, 정상적으로 작동했습니다. 내가 컴파일했는지 여부는 기억이 나지 않지만 진실은 동일한 VS 프로젝트, 동일한 코드, GPU가있는 동일한 컴퓨터라는 사실입니다.

그래서 아무도 그 이유를 설명 할 수 있습니까? 그리고 나는 더 이상 똑같은 이상 행동을 기대해야만 하는가?

#include <iostream> 
#include <string> 
#include <iomanip> 
#include <cuda_runtime.h> 
#include <cublas_v2.h> 

const int N = 5; 
#define IDX2F(i,j) ((i) * N + j) 

void fail(const cudaError_t& cudaStatus, const std::string& errorMessage) { 
    if (cudaStatus != cudaSuccess) { 
     std::cerr << errorMessage << std::endl; 
     exit(EXIT_FAILURE); 
    } 
} 

void fail(const cublasStatus_t& status, const std::string& errorMessage) { 
    if (status != CUBLAS_STATUS_SUCCESS) { 
     std::cerr << errorMessage << std::endl; 
     exit(EXIT_FAILURE); 
    } 
} 

void printMatrix(const double *C) { 
    for (int i=0; i<N; i++) { 
     for (int j=0; j<N; j++) { 
      std::cout << std::fixed << std::setprecision(2) << C[IDX2F(i,j)] << ' '; 
     } 
     std::cout << std::endl; 
    } 
    std::cout << std::endl; 
} 

int main(int argc, char **argv) { 
    cudaError_t cudaStatus; 
    cublasStatus_t status; 
    cublasHandle_t handle; 

    double *A = new double[N*N]; 
    double *devPtrA; 

    double *B = new double[N*N]; 
    double *devPtrB; 

    double *C = new double[N*N]; 
    double *devPtrC; 

    for (int i=0; i<N; i++) 
     for (int j=0; j<N; j++) 
      A[IDX2F(i,j)] = i + j; 

    for (int i=0; i<N; i++) 
     for (int j=0; j<N; j++) 
      B[IDX2F(i,j)] = i + j * 0.5; 

    // do not have to set anything into matrix C, because beta = 0 

    // allocate mamory on GPU 
    cudaStatus = cudaMalloc((void**)&devPtrC, N*N*sizeof(*C)); 
    fail(cudaStatus, "device memory allocation failed"); 

    cudaStatus = cudaMalloc((void**)&devPtrA, N*N*sizeof(*A)); 
    fail(cudaStatus, "device memory allocation failed"); 

    cudaStatus = cudaMalloc((void**)&devPtrB, N*N*sizeof(*B)); 
    fail(cudaStatus, "device memory allocation failed"); 

    // create GPU handle 
    status = cublasCreate(&handle); 
    fail(status, "CUBLAS initialization failed"); 

    // copying matrices from host to GPU 
    status = cublasSetMatrix(N, N, sizeof (*B), B, N, devPtrB, N); 
    fail(status, "failed to load data from host to GPU"); 

    status = cublasSetMatrix(N, N, sizeof (*A), A, N, devPtrA, N); 
    fail(status, "failed to load data from host to GPU"); 

    const double ONE = 1; 
    const double ZERO = 0; 

    printMatrix(A); 
    printMatrix(B); 

    status = cublasDgemm( handle, 
          CUBLAS_OP_N, CUBLAS_OP_N, 
          N, N, N, 
          &ONE, 
          devPtrA, N, 
          devPtrB, N, 
          &ZERO, 
          devPtrC, N); 

    fail(status, "error cublasDgemm"); 

    status = cublasGetMatrix(N, N, sizeof (*C), devPtrC, N, C, N); 
    fail(status, "could not load result back from GPU to host"); 

    printMatrix(C); 

    status = cublasDestroy(handle); 
    fail(status, "could not destroy CUBLAS handle"); 

    cudaStatus = cudaFree(devPtrC); 
    fail(cudaStatus, "device memory freeing failed"); 

    cudaStatus = cudaFree(devPtrB); 
    fail(cudaStatus, "device memory freeing failed"); 

    cudaStatus = cudaFree(devPtrA); 
    fail(cudaStatus, "device memory freeing failed"); 

    delete[] C; 
    delete[] B; 
    delete[] A; 

    return EXIT_SUCCESS; 
} 
+1

내지 [CUDA SDK (http://developer.nvidia.com/gpu-computing-sdk) 상이한 샘플을 실행 해 그들이 잘 작동하는지 아닌지 확인하십시오. 내 경험에 따르면 cuBLAS 자체는 매우 안정적이어서 산발적 인 하드웨어 결함이있을 수 있습니다. – aland

+0

당신이 옳았던 것처럼 보입니다. 결코 다시는이 문제를 놓치지 마십시오. – Ixanezis

답변

2

영업 이익 (B) 를 CUBLAS_OP_T해야합니다 여기

내가 실행 된 코드입니다. .

상태 = cublasDgemm (핸들 CUBLAS_OP_N, CUBLAS_OP_T, N, N, N, & ONE, devPtrA, N, devPtrB, N, & ZERO, devPtrC, N); . . . . 정의는 : C = α OP (A) OP (B) + β의 C http://docs.nvidia.com/cuda/cublas/index.html#topic_8_1

관련 문제