在 printf / cout 中使用 thrust
Using thrust with printf / cout
我正在尝试学习如何将 CUDA 与 thrust 一起使用,我看到了一些代码,其中 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 次消息 "Call for value : " 后跟一个数字。
现在,如果我包含 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 上 运行 实际上是什么?我猜,至少发送到 stdout 需要一些 CPU 工作。
- Why does it work with printf?
因为 NVIDIA 为支持设备 ABI(计算能力 >= 2.0)的所有硬件添加了对内核 printf 的运行时支持。设备代码中有主机 printf
的模板重载,它提供(几乎)标准 C 风格 printf
功能。您必须在设备代码中包含 cstdio
或 stdio.h
才能使此机制起作用。
- Why does it not work with cout?
因为 NVIDIA 尚未在 CUDA 设备运行时实现任何形式的 C++ iostream 样式I/O支持。
- What is actually run on GPU?
设备运行时维护一个 FIFO 缓冲区,供内核代码在内核执行期间通过 printf 调用写入。设备缓冲区由 CUDA 驱动程序复制,并在内核执行结束时回显到标准输出。没有记录确切的启发式和机制,但我假设格式字符串和输出存储到 FIFO 缓冲区,然后由 CPU 驱动程序解析,然后通过内核启动的某种回调打印 API. runtime API 提供了一个 function 来控制 printf FIFO 的大小。
我正在尝试学习如何将 CUDA 与 thrust 一起使用,我看到了一些代码,其中 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 次消息 "Call for value : " 后跟一个数字。
现在,如果我包含 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 上 运行 实际上是什么?我猜,至少发送到 stdout 需要一些 CPU 工作。
- Why does it work with printf?
因为 NVIDIA 为支持设备 ABI(计算能力 >= 2.0)的所有硬件添加了对内核 printf 的运行时支持。设备代码中有主机 printf
的模板重载,它提供(几乎)标准 C 风格 printf
功能。您必须在设备代码中包含 cstdio
或 stdio.h
才能使此机制起作用。
- Why does it not work with cout?
因为 NVIDIA 尚未在 CUDA 设备运行时实现任何形式的 C++ iostream 样式I/O支持。
- What is actually run on GPU?
设备运行时维护一个 FIFO 缓冲区,供内核代码在内核执行期间通过 printf 调用写入。设备缓冲区由 CUDA 驱动程序复制,并在内核执行结束时回显到标准输出。没有记录确切的启发式和机制,但我假设格式字符串和输出存储到 FIFO 缓冲区,然后由 CPU 驱动程序解析,然后通过内核启动的某种回调打印 API. runtime API 提供了一个 function 来控制 printf FIFO 的大小。