如何解决为什么 printf() 在内核中工作,而使用 std::cout 却不能?
我一直在探索并行编程领域,并用 Cuda 和 SYCL 编写了基本内核。我遇到过必须在内核中打印的情况,我注意到内核中的 std::cout
不起作用而 printf
起作用。例如,考虑以下 SYCL 代码 -
这有效 -
void print(float*A,size_t N){
buffer<float,1> Buffer{A,{N}};
queue Queue((intel_selector()));
Queue.submit([&Buffer,N](handler& Handler){
auto accessor = Buffer.get_access<access::mode::read>(Handler);
Handler.parallel_for<dummyClass>(range<1>{N},[accessor](id<1>idx){
printf("%f",accessor[idx[0]]);
});
});
}
而如果我用 printf
替换 std::cout<<accessor[idx[0]]
它会引发编译时错误说 - Accessing non-const global variable is not allowed within SYCL device code.
类似的事情发生在 CUDA 内核上。
这让我想到了导致这种行为的 printf
和 std::coout
之间可能有什么区别。
另外假设如果我想实现一个从 GPU 调用的自定义打印函数,我应该怎么做?
TIA
解决方法
在 SYCL 中,出于与 answer for CUDA code 中列出的原因类似的原因,您不能将 std::cout
用于未在主机上运行的代码的输出。
这意味着如果您在“设备”(例如 GPU)上运行内核代码,那么您需要使用 stream
类。 SYCL developer guide section called Logging 中有关于此的更多信息。
这让我想到了导致这种行为的 printf 和 std::cout 之间的区别可能是什么。
是的,有区别。在您的内核中运行的 printf()
不是标准 C 库 printf()
。对设备上的函数进行了不同的调用(其代码已关闭,如果它存在于 CUDA C 中)。该函数使用 NVIDIA GPU 上的硬件机制 - 内核线程打印的缓冲区,该缓冲区被发送回主机端,然后 CUDA 驱动程序将其转发到启动内核的进程的标准输出文件描述符。
std::cout
没有得到这种编译器辅助的替换/劫持 - 它的代码与 GPU 完全无关。
但是 - 我已经实现了一个类似于 std::cout
的机制,用于 GPU 内核;有关详细信息和链接,请参阅我的 this answer 此处的 SO。
这意味着我必须自己回答你的第二个问题:
如果我想实现一个从 GPU 调用的自定义打印函数,我应该怎么做?
除非您可以访问未公开的 NVIDIA 内部结构 - 唯一的方法是在主机端使用 printf()
调用而不是 C 标准库或系统调用。您本质上需要在低级原始 I/O 设施上模块化您的整个流。这绝非易事。
没有 __device__
版本的 std::cout
,因此只能在设备代码中使用 printf
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。