使用printf / cout推力

时间:2016-04-26 04:48:25

标签: cuda thrust

我正在尝试学习如何使用带有推力的CUDA,我已经看到了一些代码,其中printf函数似乎是从设备中使用的。

考虑以下代码:

#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 ++流的等效项替换printf行

std::cout << "Call for value : " << val << std::endl;

我从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
  1. 为什么它适用于printf?
  2. 为什么 不能与cout一起使用?
  3. GPU上实际运行的是什么?我猜,至少发送到stdout需要一些CPU工作。

1 个答案:

答案 0 :(得分:10)

  
      
  1. 为什么它适用于printf?
  2.   

因为NVIDIA为所有支持设备ABI的硬件(计算能力&gt; = 2.0)添加了对内核内printf的运行时支持。设备代码中的主机printf存在模板重载,提供(几乎)标准C样式printf功能。您必须在设备代码中加入cstdiostdio.h才能使此机制生效。

  
      
  1. 为什么它不适用于cout?
  2.   

因为NVIDIA尚未在CUDA设备运行时内实现任何形式的C ++ iostream样式I / O支持。

  
      
  1. GPU上实际运行的是什么?
  2.   

设备运行时维护一个FIFO缓冲区,供内核代码在内核执行期间通过printf调用写入。设备缓冲区由CUDA驱动程序复制,并在内核执行结束时回显到stdout。确切的启发式和机制没有记录,但我假设格式字符串和输出存储到FIFO缓冲区,然后由CPU驱动程序解析,然后通过内核启动API的某种回调打印。运行时API提供function来控制printf FIFO的大小。