【发布时间】:2016-08-19 17:21:40
【问题描述】:
我正在尝试学习如何将 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 并将 printf 行替换为基于 C++ 流的等效项
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
- 为什么它可以与 printf 一起使用?
- 为什么它不与 cout 一起工作?
- GPU 上实际运行的是什么?我猜,至少发送到标准输出需要一些 CPU 工作。
【问题讨论】:
-
printf被“重载”为__device__函数,而cout不是。您需要显式“重载”打印功能,因为您需要正确处理输出缓冲区。看一下simplePrintf示例,您就会对为什么需要显式重载以及如何做到这一点有所了解。由于cout只是__host__函数,nvcc无法编译它。