2016-07-18 6 views
0

私は推力:: raw_pointer_castを使用して生ポインタをキャスターでキャッチしようとしています。私はfloatへのポインタを渡す複数のアプローチを試みましたが、メモリの競合と2つのintellisenseエラーが発生し続けます:: system :: cuda :: thrustにはメンバ "system_error"がなく、メンバ "cuda_category"もありません。奇妙なことは、特にBULKを参照していないにもかかわらず、BULKライブラリの一部であると思われるプログラムthrow_on_error.hppのエラーと思われることです。私はC++を初めて使っているので、ポインタを誤解している可能性があります。あるいは、ある種のインクルードがありません。"system_error"と "cuda_category"に特別に名前空間の推論:: system :: cuda ::推力

以下は、動作させようとしているコードのバージョンです。どんな助けでも大歓迎です。

#include <iostream> 
#include <thrust/device_vector.h> 
#include <thrust/host_vector.h> 
#include <thrust/sort.h> 
#include <thrust/execution_policy.h> 
#include <thrust/for_each.h> 
#include <thrust/sequence.h> 
#include <cstdlib> 
#include <ctime> 
#include <vector> 
#include <algorithm> 
#include <memory.h> 
#include <cstdio> 
#include <thread> 
#include <thrust/copy.h> 
#include <thrust/iterator/zip_iterator.h> 
#include <thrust/reduce.h> 


using namespace std; 

const int num_segs = 1; // number of segments to sort 
const int num_vals = 5; // number of values in each segment 


template <typename T> 
struct sort_vector 
{ 

    T *Ndata; 
    T *Ddata; 
    T *answer; 

    sort_vector(T *_Ndata, T *_Ddata, float *a) : Ndata(_Ndata), Ddata(_Ddata), answer(a) {}; 


    __host__ __device__ void operator()(int idx) 
    { 
     thrust::sort(thrust::seq, Ndata + idx*num_vals, Ndata + ((idx + 1)*num_vals)); 
     thrust::sort(thrust::seq, Ddata + idx*num_vals, Ddata + ((idx + 1)*num_vals)); 
     *answer = thrust::reduce(thrust::device, Ddata + idx*num_vals, Ddata + ((idx + 1)*num_vals)); 

    } 
}; 

int main() { 

    thrust::device_vector<float> d_Ndata(num_segs*num_vals); 
    d_Ndata[0] = 30; 
    d_Ndata[1] = 5.5; 
    d_Ndata[2] = 60; 
    d_Ndata[3] = 21; 
    d_Ndata[4] = 2; 

    thrust::device_vector<float> d_Ddata(num_segs*num_vals); 
    d_Ddata[0] = 50; 
    d_Ddata[1] = 9.5; 
    d_Ddata[2] = 30; 
    d_Ddata[3] = 8.1; 
    d_Ddata[4] = 1; 

    cout << "original norm" << endl; 
    int f = 0; 
    while (f < num_segs*num_vals){ 
     cout << d_Ndata[f] << endl; 
     f++; 
    } 

    cout << "original dut" << endl; 
    int g = 0; 
    while (g < num_segs*num_vals){ 
     cout << d_Ddata[g] << endl; 
     g++; 
    } 

    thrust::device_vector<int> d_idxs(num_segs); 
    thrust::sequence(d_idxs.begin(), d_idxs.end()); 

    float *answer = (float*)malloc(sizeof(float)); 

    cudaStream_t s1; 
    cudaStreamCreate(&s1); 


    clock_t start; 
    double duration; 
    start = clock(); 

    thrust::for_each(thrust::cuda::par.on(s1), 
     d_idxs.begin(), 
    d_idxs.end(), sort_vector<float>(thrust::raw_pointer_cast(d_Ndata.data()), thrust::raw_pointer_cast(d_Ddata.data()), thrust::raw_pointer_cast(answer))); 

    cudaStreamSynchronize(s1); 

    cout << "sum" << endl; 
    cout << answer << endl; 

    //free(answer); 

    cudaStreamDestroy(s1); 


    duration = (clock() - start)/(double)CLOCKS_PER_SEC; 
    cout << "time " << duration << endl; 

    cin.get(); 
    return 0; 
} 

答えて

1

主な問題はここにある:

float *answer = (float*)malloc(sizeof(float)); 

これはホストメモリに割り当てを作成しています。あなたはその後、ファンクタにそのポインタを渡す場合:

thrust::raw_pointer_cast(answer) 

あなたは、デバイスのコードで実行されますファンクタにホストメモリへのポインタを渡しています。ファンクタがその場所にアクセスしようとすると、不正なアクセスになります。 CUDAでは、デバイスコードはホストポインタの場所に直接アクセスすることはできず、その逆もあります(ここでは実行されていないさまざまな概念は無視されます)。

だからあなた数子のコードがこれを行うとき:それは*answerに書き込もうとすると、不正なアクセスをトリガーする

*answer = thrust::reduce(thrust::device, Ddata + idx*num_vals, Ddata + ((idx + 1)*num_vals)); 

直接的な解決策は、デバイスメモリの適切に割り当てられた場所を指すようにanswerを作成することです。次のコードは、変更を示し、エラーなしで実行されます。

$ cat t1190.cu 
#include <iostream> 
#include <thrust/device_vector.h> 
#include <thrust/host_vector.h> 
#include <thrust/sort.h> 
#include <thrust/execution_policy.h> 
#include <thrust/for_each.h> 
#include <thrust/sequence.h> 
#include <cstdlib> 
#include <ctime> 
#include <vector> 
#include <algorithm> 
#include <memory.h> 
#include <cstdio> 
#include <thread> 
#include <thrust/copy.h> 
#include <thrust/iterator/zip_iterator.h> 
#include <thrust/reduce.h> 


using namespace std; 

const int num_segs = 1; // number of segments to sort 
const int num_vals = 5; // number of values in each segment 


template <typename T> 
struct sort_vector 
{ 

    T *Ndata; 
    T *Ddata; 
    T *answer; 

    sort_vector(T *_Ndata, T *_Ddata, float *a) : Ndata(_Ndata), Ddata(_Ddata), answer(a) {}; 


    __host__ __device__ void operator()(int idx) 
    { 
     thrust::sort(thrust::seq, Ndata + idx*num_vals, Ndata + ((idx + 1)*num_vals)); 
     thrust::sort(thrust::seq, Ddata + idx*num_vals, Ddata + ((idx + 1)*num_vals)); 
     *answer = thrust::reduce(thrust::device, Ddata + idx*num_vals, Ddata + ((idx + 1)*num_vals)); 

    } 
}; 

int main() { 

    thrust::device_vector<float> d_Ndata(num_segs*num_vals); 
    d_Ndata[0] = 30; 
    d_Ndata[1] = 5.5; 
    d_Ndata[2] = 60; 
    d_Ndata[3] = 21; 
    d_Ndata[4] = 2; 

    thrust::device_vector<float> d_Ddata(num_segs*num_vals); 
    d_Ddata[0] = 50; 
    d_Ddata[1] = 9.5; 
    d_Ddata[2] = 30; 
    d_Ddata[3] = 8.1; 
    d_Ddata[4] = 1; 

    cout << "original norm" << endl; 
    int f = 0; 
    while (f < num_segs*num_vals){ 
     cout << d_Ndata[f] << endl; 
     f++; 
    } 

    cout << "original dut" << endl; 
    int g = 0; 
    while (g < num_segs*num_vals){ 
     cout << d_Ddata[g] << endl; 
     g++; 
    } 

    thrust::device_vector<int> d_idxs(num_segs); 
    thrust::sequence(d_idxs.begin(), d_idxs.end()); 

    thrust::device_vector<float> dv_answer(1); 
    //float *answer = (float*)malloc(sizeof(float)); 

    cudaStream_t s1; 
    cudaStreamCreate(&s1); 


    clock_t start; 
    double duration; 
    start = clock(); 

    thrust::for_each(thrust::cuda::par.on(s1), 
     d_idxs.begin(), 
    d_idxs.end(), sort_vector<float>(thrust::raw_pointer_cast(d_Ndata.data()), thrust::raw_pointer_cast(d_Ddata.data()), thrust::raw_pointer_cast(dv_answer.data()))); 

    cudaStreamSynchronize(s1); 

    cout << "sum" << endl; 
    cout << dv_answer[0] << endl; 

    //free(answer); 

    cudaStreamDestroy(s1); 


    duration = (clock() - start)/(double)CLOCKS_PER_SEC; 
    cout << "time " << duration << endl; 

    return 0; 
} 
$ nvcc -std=c++11 t1190.cu -o t1190 
$ ./t1190 
original norm 
30 
5.5 
60 
21 
2 
original dut 
50 
9.5 
30 
8.1 
1 
sum 
98.6 
time 0.000919 
$ 

私はIntellisenseエラーについて説明しません。 Intellisenseは一般的にCUDAでうまく機能しません。インテリセンスを見てきたように、実際にコンパイルされたものにフラグを立てることができます(この問題のこのコードなど)。 CUDAコードが正しくコンパイルされている場合、Intellisenseが報告した問題は安全に無視できる可能性があります。

追加のいくつかのコメントのよう:

  1. あなたはファンクタ内からスラストアルゴリズムを実行し、スラスト初心者のために、ここで奇妙な道を下って行くように見えます。技術的に間違ったことは何もありませんが、通常、このタイプのコードは一般的な推力の使用ではなく特定の状況に予約されています。この例ではnum_segsが1であるため、この作業をすべて実行するために1つのCUDAスレッドが実行されますが、これは決して実行できません。あなたが後でスケールアップするつもりなら、素晴らしい。私はこれまで同様のコメントをしていますので、ここで詳しく説明しません。

  2. このファンクタは、結果を格納するために単一の場所(*answer)に書き込みます。これを2つ以上のスレッドに拡大する場合は、ファンクタが書き込むための複数の場所を指定する必要があります(スレッド内またはベクターの要素ごとにfor_eachに渡す)。そうでなければスレッドは上書きされます互いの結果。

+0

ありがとうございました!はい、並列プログラムを実装するためのツールを集めようとしています。何千ものウィンドウが同じプログラム(すでに書かれていますが、遅すぎてGPUのコンピューティング能力を最大限に引き出すことはありません)を実行します。はい、私は間違いなく、(まだこれをテストし始めていない)ファンクタのすべての出力を収集するために、回答ベクトルにある種のインデックスを実装することを考えました、それを指摘してくれてありがとう。 – gracie