私は推力を使ってCUDAを使用する方法を学ぼうとしており、printf関数がデバイスから使用されていると思われるコードをいくつか見てきました。printf/coutで推力を使用する
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <cstdio>
struct functor
{
__host__ __device__
void operator()(int val)
{
printf("Call for value : %d\n", val);
}
};
int main()
{
thrust::host_vector<int> cpu_vec(100);
for(int i = 0 ; i < 100 ; ++i)
cpu_vec[i] = i;
thrust::device_vector<int> cuda_vec = cpu_vec; //transfer to GPU
thrust::for_each(cuda_vec.begin(),cuda_vec.end(),functor());
}
これが正常に動作しているようだと100回のメッセージ出力し、「値のためのコール:」数字が続く
は、このコードを考えてみましょう。私はのiostreamが含まれており、C++ストリームベースの同等std::cout << "Call for value : " << val << std::endl;
とprintfのラインを交換する場合
は、今私はNVCCからコンパイル警告を取得し、コンパイルされたプログラムは、何も印刷されません。
warning: address of a host variable "std::cout" cannot be directly taken in a device function
warning: calling a __host__ function from a __host__ __device__ function is not allowed
warning: calling a __host__ function("std::basic_ostream<char, std::char_traits<char> >::operator <<") from a __host__ __device__ function("functor::operator()") is not allowed
- なぜそれがprintf関数で動作しますか?
- なぜそれがではないはcoutで動作しますか?
- 実際にGPUで実行されるのは何ですか?少なくとも、標準出力への送信にはCPUの作業が必要になると思います。
'printf'は' __device__'関数として「オーバーロード」されていますが、 'cout'はそうではありません。出力バッファを適切に処理する必要があるため、印刷機能の明示的な「オーバーロード」が必要です。 'simplePrintf'の例を見てください。なぜあなたは明示的なオーバーロードが必要か、どうやってそれをやることができるのかを感じるでしょう。 'cout'は' __host__'関数だけなので、 'nvcc'はそれをコンパイルできません。 – JackOLantern