2012-04-25 133 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調用的結果看起來相當隨意,並且輸出錯誤的索引。

任何人對我的問題有很好的回答?我現在有點難過:(

+0

嘗試初始化'max_idx'和'內min_idx'爲'int'取代'INT *',並通過引用它們傳遞到CUBLAS'&max_idx' – Vanwaril 2012-04-25 19:42:52

回答

4

您對cublasIdamaxcublasIdamin調用的一個參數是錯誤的.BLAS級別1調用中的incx參數應始終是單詞輸入的跨度,而不是字節。因此,我懷疑你想要更多的東西一樣:

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"); 

使用sizeof(double)您告訴程序使用的8一大步,這將有溢出輸入數組,進入未初始化的內存分配的存儲的電話。我想你實際上在d_values有一個1的步幅。


編輯:這是一個完整的可正常運行的示例。注意我換碼爲單精度,因爲我現在並沒有獲得雙精度能力的硬件:

#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

不幸的是,這並沒有解決問題,我有。仍然返回似乎隨機結果。 – ssnielsen 2012-04-25 09:32:31

+0

@ssnielsen:在我運行完我的答案中添加的repro case後會發生什麼? – talonmies 2012-04-25 20:39:13

+0

它工作得很好。我沒有注意到1-indexing以及CUBLAS處理數字絕對值並查看數字是否被簽名的事實。 – ssnielsen 2012-04-26 07:29:33