2012-04-25 33 views
3

CUBLASを使用して倍精度の範囲で最大値と最小値を見つける関数が正しく機能しないことがわかりました。CUBLASで最大値と最小値を見つける

void findMaxAndMinGPU(double* values, int* max_idx, int* min_idx, int n) 
{ 
    double* d_values; 
    cublasHandle_t handle; 
    cublasStatus_t stat; 
    safecall(cudaMalloc((void**) &d_values, sizeof(double) * n), "cudaMalloc  (d_values) in findMaxAndMinGPU"); 
    safecall(cudaMemcpy(d_values, values, sizeof(double) * n, cudaMemcpyHostToDevice), "cudaMemcpy (h_values > d_values) in findMaxAndMinGPU"); 
    cublasCreate(&handle); 

    stat = cublasIdamax(handle, n, d_values, sizeof(double), max_idx); 
    if (stat != CUBLAS_STATUS_SUCCESS) 
     printf("Max failed\n"); 

    stat = cublasIdamin(handle, n, d_values, sizeof(double), min_idx); 
    if (stat != CUBLAS_STATUS_SUCCESS) 
     printf("min failed\n"); 

    cudaFree(d_values); 
    cublasDestroy(handle); 
} 

値が値内で検索する場所次のよう

コードです。 max_idxとmin_idxは、見つかった数値のインデックスです。 CUBLAS呼び出しの結果はむしろランダムに見え、間違ったインデックスを出力します。

誰かが私の問題に対するゴリの良い答えを持っていますか?私は両方のcublasIdamaxcublasIdamin呼び出しに

+0

は残念ながら、これは私が持っている問題が解決しない 'int型*を' '初期化max_idx'と'と 'int'の代わりに、内部min_idx'試してみてください、そして、参照によってCUBLASに渡す'& – Vanwaril

答えて

4

:(現時点では、あなたの引数の一つ少し悲しい間違っている。1呼び出しは常に言葉ではなく、バイト単位で入力のストライドでなければなりませんBLASレベルのincx引数。あなたが入力配列のと初期化されていないメモリに割り当てられたストレージをオーバーラン電話を持っているであろう、8のストライドを使用するルーチンを言っているsizeof(double)を使用することにより

stat = cublasIdamax(handle, n, d_values, 1, max_idx); 
if (stat != CUBLAS_STATUS_SUCCESS) 
    printf("Max failed\n"); 

stat = cublasIdamin(handle, n, d_values, 1, min_idx); 
if (stat != CUBLAS_STATUS_SUCCESS) 
    printf("min failed\n"); 

:だから私はあなたがより多くのような何かをしたいと思われます。あなたは実際には1のストライドがd_valuesにあると推測します。


編集:これは正しく動作する完全な実行可能な例です。コンパイルと実行が、この与えたときに

#include <cuda_runtime.h> 
#include <cublas_v2.h> 
#include <cstdio> 
#include <cstdlib> 
#include <sys/time.h> 


typedef float Real; 

void findMaxAndMinGPU(Real* values, int* max_idx, int* min_idx, int n) 
{ 
    Real* d_values; 
    cublasHandle_t handle; 
    cublasStatus_t stat; 
    cudaMalloc((void**) &d_values, sizeof(Real) * n); 
    cudaMemcpy(d_values, values, sizeof(Real) * n, cudaMemcpyHostToDevice); 
    cublasCreate(&handle); 

    stat = cublasIsamax(handle, n, d_values, 1, max_idx); 
    if (stat != CUBLAS_STATUS_SUCCESS) 
     printf("Max failed\n"); 

    stat = cublasIsamin(handle, n, d_values, 1, min_idx); 
    if (stat != CUBLAS_STATUS_SUCCESS) 
     printf("min failed\n"); 

    cudaFree(d_values); 
    cublasDestroy(handle); 
} 

int main(void) 
{ 
    const int vmax=1000, nvals=10000; 

    float vals[nvals]; 
    srand (time(NULL)); 
    for(int j=0; j<nvals; j++) { 
     vals[j] = float(rand() % vmax); 
    } 

    int minIdx, maxIdx; 
    findMaxAndMinGPU(vals, &maxIdx, &minIdx, nvals); 

    int cmin = 0, cmax=0; 
    for(int i=1; i<nvals; i++) { 
     cmin = (vals[i] < vals[cmin]) ? i : cmin; 
     cmax = (vals[i] > vals[cmax]) ? i : cmax; 
    } 

    fprintf(stdout, "%d %d %d %d\n", minIdx, cmin, maxIdx, cmax); 

    return 0; 
} 

は:

$ g++ -I/usr/local/cuda/include -L/usr/local/cuda/lib cublastest.cc -lcudart -lcublas 
$ ./a.out 
273 272 85 84 

ノートはCUBLASをFORTRANに従っていることを私は現在、倍精度可能なハードウェアへのアクセスを持っていないので、私は単精度にコードを切り替える注意ゼロ索引ではなく1つの索引付けを使用するため、CUBLASとCPUのバージョンには1の違いがあります。説明から

+0

をmax_idx' 。まだランダムな結果が出ているものを返す。 – ssnielsen

+0

@ssnielsen:答えに追加した完全な復習ケースを実行するとどうなりますか? – talonmies

+0

それは完全に正常に動作します。私は1インデックス作成だけでなく、CUBLASがその数字の絶対値で動作し、その数字が署名されているかどうかを調べていることに気づいていませんでした。 – ssnielsen

関連する問題