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

Cuda 为什么printf()在内核中工作,而使用std::cout则不行?,cuda,printf,cout,sycl,Cuda,Printf,Cout,Sycl,我一直在探索并行编程领域,并用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]

我一直在探索并行编程领域,并用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]]);
       });
    });
}
然而,如果我用std::cout替换printf没有std::cout的设备版本,因此只有printf可以在设备代码中使用。

没有std::cout的设备版本,因此只有printf可以在设备代码中使用

这让我想到printf和std::cout之间的区别是什么导致了这种行为

是的,有区别。在内核中运行的printf不是标准的C库printf。如果CUDA C中存在代码已关闭的设备上函数,则会进行不同的调用。该函数使用NVIDIA GPU上的硬件机制-内核线程打印到的缓冲区,该缓冲区会发送回主机端,然后CUDA驱动程序将其转发给启动内核的进程的标准输出文件描述符

std::cout没有得到这种编译器辅助的替换/劫持——它的代码在GPU上根本不相关

然而,我已经实现了一个类似std::cout的机制,用于GPU内核;有关更多信息和链接,请参见我的文章

这意味着我必须自己回答你的第二个问题:

如果我想实现一个从GPU调用的自定义打印函数,我应该怎么做

除非您可以访问未公开的NVIDIA内部构件,否则唯一的方法是在主机端使用printf调用,而不是使用C标准库或系统调用。基本上,您需要通过低级基本I/O设施对整个流进行模块化。这绝非小事

这让我想到printf和std::cout之间的区别是什么导致了这种行为

是的,有区别。在内核中运行的printf不是标准的C库printf。如果CUDA C中存在代码已关闭的设备上函数,则会进行不同的调用。该函数使用NVIDIA GPU上的硬件机制-内核线程打印到的缓冲区,该缓冲区会发送回主机端,然后CUDA驱动程序将其转发给启动内核的进程的标准输出文件描述符

std::cout没有得到这种编译器辅助的替换/劫持——它的代码在GPU上根本不相关

然而,我已经实现了一个类似std::cout的机制,用于GPU内核;有关更多信息和链接,请参见我的文章

这意味着我必须自己回答你的第二个问题:

如果我想实现一个从GPU调用的自定义打印函数,我应该怎么做

除非您可以访问未公开的NVIDIA内部构件,否则唯一的方法是在主机端使用printf调用,而不是使用C标准库或系统调用。基本上,您需要通过低级基本I/O设施对整个流进行模块化。这绝非小事。

在SYCL中,您不能在主机上未运行的代码上使用std::cout进行输出,原因与中列出的类似

这意味着,如果您在设备(如GPU)上运行内核代码,则需要使用stream类。有关这方面的详细信息,请参见SYCL中的。

,在主机上未运行的代码上,您不能使用std::cout作为输出,原因与中列出的类似


这意味着,如果您在设备(如GPU)上运行内核代码,则需要使用stream类。有关这方面的更多信息,请参阅。

感谢您的回复@Oblivion。请详细说明一下好吗?@AtharvaDubey要从内核运行函数,它必须定义为全局或设备。你可以调用printf,因为有一个设备printf定义。哦,好的,非常感谢。有什么方法可以定义我的自定义函数吗?@Oblivion我想你的意思是没有设备版本可能会感兴趣谢谢你的回复@Oblivion。请详细说明一下好吗?@AtharvaDubey要从内核运行函数,它必须定义为全局或设备。你可以调用printf,因为有一个设备printf定义。哦,好的,非常感谢。有什么方法可以定义我的自定义函数吗?@Oblivion我想你的意思是没有设备版本可能很有意思谢谢@einpoklum的回答,这就清楚了up@AtharvaDubey:如果它回答了问题,请接受它…为了说明为什么printf在SYCL示例代码中工作,我想补充一点,这不是标准的SYCL,但有些实现碰巧支持内核中的printf作为扩展。对于cout-like机制,SYCL标准提供了str
正如罗德在回答中指出的那样,eam课堂。非常感谢@einpoklum的回答,这就清楚了up@AtharvaDubey:如果它回答了这个问题,请接受它…为了说明为什么printf在SYCL示例代码中工作,我想补充一点,这不是标准的SYCL,但是一些实现碰巧在内核中支持printf作为扩展。对于cout-like机制,SYCL标准提供了stream类,正如Rod在回答中指出的。您能否详细说明stream类与std::ostream的相似性或不同性?用法非常相似,即您可以调用mystream,您能否详细说明stream类的相似性,或者与std::ostream不同?用法非常相似,即您称之为mystream