2011-12-24 28 views
0

CUDA + CUBLASを使用して私の最初のプログラムを書きました。 'cublasDgemm'関数を使用して、2つのN * N行列の積を計算します。CUBLASは予期せず動作します

私は自分のプログラムを立ち上げていた頃、同じ誤った答えを得ていました(例えば、5を含む1 * 1行列に要素6を含む1 * 1行列を乗算すると、 30ではなく36である)。 プログラムを何度もチェックしましたが、成功しませんでした。しかし、私がそれに復帰したとき(すなわち再起動後)、それはうまくいった。私はそれを再コンパイルしたかどうか覚えていませんが、真実は同じ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

OP(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