__device__
リンクされた Talonmies の質問に記載されているように、CUDA 関数 (または など)から Thrust を呼び出すことはできません__global__
。ただし、これは、Thrust でデバイス メモリに既にあるデータを使用できないという意味ではありません。代わりに、生データをラップする Thrust ベクトルを使用して、ホストから目的の Thrust 関数を呼び出します。例えば
//raw pointer to device memory
unsigned int * raw_data;
unsigned int * raw_keys;
//allocate device memory for data and keys
cudaMalloc((void **) &raw_data, N_data * sizeof(int));
cudaMalloc((void **) &raw_keys, N_keys * sizeof(int));
//populate your device pointers in your kernel
kernel<<<...>>>(raw_data, raw_keys, ...);
...
//wrap raw pointer with a device_ptr to use with Thrust functions
thrust::device_ptr<unsigned int> dev_data_ptr(raw_data);
thrust::device_ptr<unsigned int> dev_keys_ptr(raw_keys);
//use the device memory with a thrust call
thrust::sort_by_key(d_keys, d_keys + N_keys, dev_data_ptr);
が指すデバイス メモリは、 でラップしてもデバイス メモリ内にraw_data
あるため、ホストから Thrust 関数を呼び出している間、ホストからデバイスに、またはその逆にメモリをコピーする必要はありません。つまり、デバイス メモリを使用して、GPU で直接並べ替えています。唯一のオーバーヘッドは、Thrust カーネルの起動と raw デバイス ポインターのラップです。raw_keys
Thrust::device_ptr
もちろん、後で通常の CUDA カーネルで使用する必要がある場合は、生のポインターを取得できます。
unsigned int * raw_ptr = thrust::raw_pointer_cast(dev_data_ptr);
unsigned long long int
またはunsigned int
をデータのキーとして使用する場合unsigned int
、Thrust はテンプレート化されているため、これは問題ではありません。つまり、 の署名sort_by_key
は
template<typename RandomAccessIterator1 , typename RandomAccessIterator2 >
void thrust::sort_by_key(
RandomAccessIterator1 keys_first,
RandomAccessIterator1 keys_last,
RandomAccessIterator2 values_first )
つまり、キーとデータにさまざまなタイプを使用できます。すべてのキータイプが特定の呼び出しに対して同種である限り、Thrust はタイプを自動的に推測できるはずであり、特別なことをする必要はありません。うまくいけば、それは理にかなっています