2017-06-07 2 views
-1

CUBsegmented-reduction sumプリミティブを使用しようとしています。CUBのセグメント化されていない結果が生成されない

は、ここに私のコードです:

int main() { 


    const int N = 7; 
    const int num_segments = 3; 
    int d_offsets[]= {0,3,3,7}; 


    int *h_data  = (int *)malloc(N * sizeof(int)); 
    int *h_result = (int *)malloc(num_segments * sizeof(int)); 


    for (int i=0; i<N; i++) { 
     h_data[i] = 3; 

    } 


    int *d_data; 
    cudaMalloc((int**)&d_data, N * sizeof(int)); 
    cudaMemcpy(d_data, h_data, N * sizeof(int), cudaMemcpyHostToDevice); 


    int   *d_result; 
    cudaMalloc((int**)&d_result, num_segments * sizeof(int)); 

    void   *d_temp_storage = NULL; 
    size_t   temp_storage_bytes = 0; 


    cudaMalloc((void**)&d_temp_storage, temp_storage_bytes); 


    cub::DeviceSegmentedReduce::Sum(d_temp_storage, temp_storage_bytes, d_data, d_result, 
     num_segments, d_offsets, d_offsets + 1); 


    cudaMemcpy(h_result, d_result, num_segments*sizeof(int), cudaMemcpyDeviceToHost); 




    printf("Results:\n"); 

    for (int i=0; i<num_segments; i++) { 
     printf("CUB: %d\n", h_result[i]); 

    } 


} 

しかし、結果として、私はこれだ:

Results: 
CUB: 0 
CUB: 0 
CUB: 0 

私は問題が正確であるかを把握することはできませんが。 実際の例では、セグメントが400に等しい非常に大きな配列を持っています。 d_offsetsの宣言とメモリを割り当てる必要がないようにコードを最適化できますか?

+0

ありがとうございます私はそれを忘れてしまった:(あなたには等しい長さのセグメントを減らす方法がありますか?実際には、私は大きなセグメントを含む大きな配列を持っています。 d_offsets @ einpoklum –

答えて

1

あなたが本当に真剣にあなたのコードをデバッグしようとしていない:

  • あなたは、デバイスのホストメモリアドレスを渡すようにしようとしていた
  • (あなたがいることを、固定)d_resultsのためのメモリの割り当てを欠落していましたメモリアドレスはd_offsetsです。もちろん、これによりCUDAランタイムエラーが発生しますが、
  • 実行時エラーはチェックされませんでした。
  • 実際に何かを実行するには2回実行する必要がありますが、1回だけCUB関数を呼び出す必要があります。nullptrをスクラッチスペースとして使用し、スクラッチスペースサイズを取得してから実際のスクラッチスペースを使用して。それは厄介なAPIですが、それはどのように動作します。

自分でコードをデバッグするときに、SOコミュニティの時間を無駄にするのは不適切です。

でも、にはのエラーをチェックする必要はありません。少なくとも、エラーを投げるなど、何らかの種類のライブラリを使用する必要があります。あなたがした場合はその - 例えば、使用して私(自己プラグ申し訳ありません)、およびCUDA Runtime API wrappers適切にあなたは、あなたがこのようなもので終わるだろうとするために必要なすべてのためにメモリを割り当てる:

#include <cub/cub.cuh> 
#include <cuda/api_wrappers.h> 
#include <vector> 
#include <cstdlib> 

int main() { 

    const int N = 7; 
    const int num_segments = 3; 
    auto h_offsets = std::vector<int> {0,3,3,7}; 

    auto h_data = std::vector<int>(N); 
    auto h_results = std::vector<int>(num_segments); 

    std::fill(h_data.begin(), h_data.end(), 3); 

    auto current_device = cuda::device::current::get(); 
    auto d_offsets = cuda::memory::device::make_unique<int[]>(
     current_device, h_offsets.size()); 
    auto d_data = cuda::memory::device::make_unique<int[]>(
     current_device, N); 
    cuda::memory::copy(
     d_offsets.get(), &h_offsets[0], h_offsets.size() * sizeof(int)); 
    cuda::memory::copy(
     d_data.get(), &h_data[0], h_data.size() * sizeof(int)); 
    auto d_results = cuda::memory::device::make_unique<int[]>(
     current_device, num_segments); 

    auto d_start_offsets = d_offsets.get(); 
    auto d_end_offsets = d_start_offsets + 1; // aliasing, see CUB documentation 

    size_t temp_storage_bytes = 0; 

    // This call merely obtains a value for temp_storage_bytes, passed here 
    // as a non-const reference; other arguments are unused 
    cub::DeviceSegmentedReduce::Sum(
     nullptr, temp_storage_bytes, d_data.get(), d_results.get(), 
     num_segments, d_start_offsets, d_end_offsets); 

    auto d_temp_storage = cuda::memory::device::make_unique<char[]>(
     current_device, temp_storage_bytes); 

    cub::DeviceSegmentedReduce::Sum(
     d_temp_storage.get(), temp_storage_bytes, d_data.get(), 
     d_results.get(), num_segments, d_start_offsets, d_end_offsets); 

    cuda::memory::copy(
     &h_results[0], d_results.get(), num_segments * sizeof(int)); 

    std::cout << "Results:\n"; 

    for (int i=0; i<num_segments; i++) { 
     std::cout << "Segment " << i << " data sums up to " << h_results[i] << "\n"; 
    } 

    return EXIT_SUCCESS; 
} 

動作します:

Results: 
Segment 0 data sums up to 9 
Segment 1 data sums up to 0 
Segment 2 data sums up to 12 

その他のヒント:

  • は、必ずコンパイラの警告を調査します。
  • などの使用cuda-memcheck間違ったデバイス/ホスト側の初期化/メモリリークを回避するために、
  • あなたが直接CUDAランタイムAPIを使用している場合は、あなた必見check every call for errors
+0

のメモリを大量に割り当てることで、初心者であり、申し訳ありませんが、愚かな質問をするのは残念です。問題を解決しようと最後に過ごす情報ですが、できませんでした。ありがとうございました。私はすべてのアドバイス@ einpoklumをやります。 –

+0

あなたのスコアが1ではないので絶対初心者として扱わなかったのですが、あなたのプロフィールを見ても、あなたはまだその資格を得ていると思います....あなたが役に立つ答えを見つけたら、それをアップ・ボードすることを検討すべきです。私はあなたがupvoteなしで少なくとも2つの質問への答えを受け入れたことに気づいた。それは間違いなくあなたの権利の範囲内ですが、私たちは通常、あまり役に立たない回答を「慎重に受け入れる」ことをします。 – einpoklum

+0

また、 "ありがとう"や "それが働いた"というコメントは必要ありません。+ upvoteを受け入れると、同じことを意味します。 – einpoklum

関連する問題