微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么 printf() 在内核中工作,而使用 std::cout 却不能?

如何解决为什么 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 内核上。 这让我想到了导致这种行为的 printfstd::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 举报,一经查实,本站将立刻删除。