4

CUBLASを使用してdoubleの範囲で最大値と最小値を検出する関数が正しく機能しない理由を理解するのに問題があります。

コードは次のとおりです。

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

ここで、valuesは検索する値です。max_idxとmin_idxは、値で見つかった数値のインデックスです。CUBLAS呼び出しの結果はかなりランダムに見え、間違ったインデックスを出力します。

私の問題に対して非常に良い答えを持っている人はいますか?私は今少し悲しいです:(

4

2 に答える 2

6

cublasIdamaxcublasIdamin呼び出しの両方に対する引数の1つが間違っています。incxBLASレベル1呼び出しの引数は、バイト単位ではなく、常にワード単位の入力のストライドである必要があります。だから私はあなたがもっと次のようなものが欲しいと思う:

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のストライドを使用するようにルーチンに指示します。これにより、呼び出しは、入力配列の割り当てられたストレージをオーバーランし、初期化されていないメモリに入れます。私はあなたが実際に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の違いがある理由です。

于 2012-04-25T09:21:42.520 に答える
2

説明から:最大の大きさの要素:http: //docs.nvidia.com/cuda/cublas/index.html#topic_6_1

if you have { 1, 2, 3, -33, 22, 11 }

結果は4になります!5ではない

abs(-33) > 22
于 2013-05-07T16:13:02.763 に答える