-3

これが推力による私のカーネル呼び出しコードです

inline void find_min_max(thrust::device_vector<Npp8u> dev_vec, Npp8u *min, Npp8u *max){
    thrust::pair<thrust::device_vector<Npp8u>::iterator,thrust::device_vector<Npp8u>::iterator> tuple;
    tuple = thrust::minmax_element(dev_vec.begin(),dev_vec.end());
    *min = *(tuple.first);
    *max = *tuple.second;
}

また、map-reduce パラダイムと単純な CPU コードを使用して、未加工の CUDA カーネルで同じアルゴリズムを実装しています。測定の結果、推力が最も遅いことがわかりました。

簡潔にするために、未加工の CUDA と推力コードを測定するためにイベントを使用しました。イベントが推力ベンチマークで機能する場合、実行時間を正しく測定していると確信しています。

これが測定セグメントです。

    ....
    cudaEvent_t start, stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start, 0);
    thrust::device_vector<Npp8u> image_dev(imageHost, imageHost+N);

    // Device vector allocation
    find_min_max(image_dev,&min,&max);

    cudaEventRecord(stop, 0);
    cudaEventSynchronize(stop);
    float elapsedTime1;
    cudaEventElapsedTime(&elapsedTime1, start, stop);
    cudaEventDestroy(start);
    cudaEventDestroy(stop);
    totalTime1 = elapsedTime1/1000
....

私の本当の質問は、推力で単純な minmax_element 関数以外のより良いアプローチを持つ可能性はありますか?

私のマシンの仕様: GeForce 635M と i7 プロセッサを搭載した asus k55v ラップトップです。

Thrustコードと CPUコードのすべてのコード

4

1 に答える 1

8

推力と比較しているコードを示しておらず、マシンの仕様 (GPU、CPU など) も提供しておらず、実際に測定された時間も教えていません。

それにもかかわらず、私はあなたのコードを取り出してテスト ケースを作成し、推力と STL を比較しました (CPU コードやその他の実装を示していないため)。

#include <stdio.h>
#include <thrust/device_vector.h>
#include <thrust/extrema.h>
#include <thrust/pair.h>
#include <algorithm>
#include <time.h>

#define N 1000000
#define LOOPS 1000

inline void find_min_max(thrust::device_vector<int> &dev_vec, int *min, int *max){
    thrust::pair<thrust::device_vector<int>::iterator,thrust::device_vector<int>::iterator> tuple;
    tuple = thrust::minmax_element(dev_vec.begin(),dev_vec.end());
    *min = *(tuple.first);
    *max = *tuple.second;
}


int main(){
    int minele, maxele;

    std::vector<int> a;
    for (int i=0; i<N; i++)
      a.push_back(rand());
    thrust::host_vector<int> h_a(N);
    thrust::copy(a.begin(), a.end(), h_a.begin());

    cudaEvent_t start, stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start, 0);
    for (int i=0; i < LOOPS; i++){
      thrust::device_vector<int> d_a = h_a;
      find_min_max(d_a,&minele,&maxele);
      }
    cudaEventRecord(stop, 0);
    cudaEventSynchronize(stop);
    float elapsedTime1, totalTime1;
    cudaEventElapsedTime(&elapsedTime1, start, stop);
    cudaEventDestroy(start);
    cudaEventDestroy(stop);
    totalTime1 = elapsedTime1/(1000*LOOPS);
    printf("thrust min element = %d, max element = %d\n", minele, maxele);
    printf("thrust time = %f\n", totalTime1);

    clock_t t;
    t = clock();
    std::vector<int>::iterator resultmax, resultmin;
    for (int i = 0; i<LOOPS; i++){
      resultmax = std::max_element(a.begin(), a.end());
      resultmin = std::min_element(a.begin(), a.end());
      }
    t = clock() - t;
    printf("STL min element = %d, max element = %d\n", *resultmin, *resultmax);
    printf("STL time = %f\n", ((float)t)/(CLOCKS_PER_SEC*LOOPS));
  return 0;
}

このコードは、CUDA 5.0、RHEL 5.5、Xeon X5560 2.8GHz CPU、および M2050 よりもやや遅い cc 2.0 デバイスである Quadro 5000 GPU を使用してコンパイルしました (11 SM 対 14)。結果は次のとおりです。

thrust min element = 1210, max element = 2147480021
thrust time = 0.001741
STL min element = 1210, max element = 2147480021
STL time = 0.004520

最小値と最大値を取得するために STL で 2 つの関数呼び出しを使用しているという事実 (c++11 標準には単一の minmax 関数呼び出しが含まれていることを知っている) を考慮し、STL 時間を半分に短縮したとしても、推力はより高速です。

あなたのケースが特別な理由について議論したい場合は、私が提供したものと同様の完全でコンパイル可能な簡単な比較コードと、あなたのマシンの仕様、および実際のタイミング結果を含めてください。

マイナーな最適化コメントとして、値ではなく参照 (&) で関数に渡すと、実行が少し速くなりますdevice_vectorfind_min_max

私の場合、host-> device_vector のコピーをタイミング ループから外すと、推力時間が 0.001741 秒から 0.000387 秒に減少します。これは、host-> device のコピーが総推力時間の約 78% であることを示しています。

編集:コードを投稿したので(取得するタイミングについては言及していませんが)、512x512 lenaグレースケール画像で実行し、セットアップで次の結果を得ました:

$ ./cpu
        Version: P5
        Comment: # Created by Imlib
        Width: 512 Height: 512
        Max value: 255
ELAPSED TIME -AVG finding max and min: 0.0014437
ELAPSED TIME -AVG finding max and min: 0.0038715
$ ./thr
Load PGM file.
        Version: P5
        Comment: # Created by Imlib
        Width: 512 Height: 512
        Max value: 255
ELAPSED TIME -AVG for kernel 1: 0.000658944
ELAPSED TIME -AVG for kernel 2: 0.000179552
$

したがって、あなたのコードであっても、私のセットアップでは推力の方が速いようです。

于 2013-05-26T06:55:50.757 に答える