将CUDA PRINTF重定向到C 流
Redirecting CUDA printf to a C++ stream
问题语句
我正在研究一个大型项目,该项目使用记录仪进行调试。由于我喜欢保留某些CUDA内核中发生的事情的踪迹,因此我试图找到一种将我的CUDA内核printf
重定向到stringstream
(或任何流)的方法,然后可以将其转发到Logger。h2>可能的解决方案
我通过使用以下代码设法进行操作:
#include <cuda.h>
#include <stdio.h>
#include <unistd.h> // dup
#include <iostream>
#include <sstream> // stringstream
#include <fstream> // ofstream
char* output_file = "printf_redirect.log";
__global__ void printf_redirect(int* src, int* res)
{
res[threadIdx.x] = threadIdx.x;
printf(" %i: Hello World!n", res[threadIdx.x]);
}
int main()
{
using namespace std;
const uint N = 2;
// Note: dummy arrays are not actually used, but this should prevent the
// compiler from discarding the printf in the kernel.
int *d_A, *d_B, *h_A, *h_B;
size_t size = N * sizeof (int);
cudaMalloc (&d_A, size);
cudaMalloc (&d_B, size);
h_A = (int*) malloc (size);
h_B = (int*) malloc (size);
cudaMemcpy (d_A, h_A, size, cudaMemcpyHostToDevice);
std::cout << "std::cout - start" << std::endl;
printf ("stdout - startn");
/// REGULAR PRINT
// Print to regular stdout
std::cout << "Output to stdout:" << std::endl;
printf_redirect<<<1,1>>> (d_A, d_B);
cudaDeviceSynchronize ();
/// REDIRECTION TO STRINGSTREAM
std::stringstream ss;
// Redirect std::cout to a stringstream
std::streambuf* backup_cout = std::cout.rdbuf ();
std::cout.rdbuf (ss.rdbuf ());
// Redirect stdout to a buffer
char buf[1024] = "";
int backup_stdout = dup (fileno (stdout));
freopen ("/dev/null", "w", stdout);
setbuf (stdout, buf);
std::cout << "Redirected output:" << std::endl;
printf_redirect<<<1,N>>> (d_A, d_B);
cudaDeviceSynchronize ();
// Add CUDA buffer to a stringstream
ss << buf;
// Write stringstream to file
std::ofstream outFile;
outFile.open (output_file);
outFile << ss.str ();
outFile.close ();
/// RESET REDIRECTION
// Redirect back to initial stdout
fflush (stdout);
setbuf (stdout, NULL);
fclose (stdout);
FILE *fp = fdopen (backup_stdout, "w");
fclose (stdout);
*stdout = *fp;
// Redirect back to initial std::cout
std::cout.rdbuf (backup_cout);
std::cout << "std::cout - end" << std::endl;
printf ("stdout - endn");
cudaMemcpy(h_B, d_B, size, cudaMemcpyDeviceToHost);
cudaFree(d_A);
cudaFree(d_B);
free (h_A);
free (h_B);
}
我使用以下问题来实现这一目标:
- 将COUT和STDOUT重定向到C 的字符串进行单位测试
- 如何在freopen(" out.txt"," a",stdout)之后将输出重定向回屏幕
运行程序,我们进入控制台:
std::cout - start
stdout - start
Output to stdout:
0: Hello World!
std::cout - end
stdout - end
和printf_redirect.log
:
Redirected output:
0: Hello World!
1: Hello World!
问题
有什么更简单的方法可以实现这一目标吗?(例如,隐藏的CUDA选项或整洁的C/C 技巧)
请注意,最终解决方案最终将进入实用程序类,以使其在实际代码中少详细。
设备侧 printf()
导致正在打印的线程的隐式序列化,因此您可能不想在生产代码中使用它。
设备侧printf()
通过将内核复制消息复制到预关注的环缓冲区来起作用。在隐式或探索设备同步(cudadevicesynchronize())时,cuda将缓冲区中的任何内容转储到 stdout
,然后清除。
您可以简单地实现自己的设备printf()
。它的性能可能不会比内置的差。唯一的缺点是您必须将环缓冲区传递到内核,并在内核返回后添加调用以处理它。
实施将是这样的:
-
创建一个带有固定数量
printf()
格式字符串和关联32位或64位参数的固定数量的缓冲区。 -
创建一个使用
atomicInc()
的设备功能来跟踪当前打印位置,并使用格式字符串和参数并将其复制到当前位置。 -
将环缓冲区传递到内核,然后将其与打印参数一起传递到设备功能。
-
创建一个主机函数,该功能采用环缓冲区,通过主机侧
sprintf()
运行格式字符串和参数,并将结果传递到Logger。
相关文章:
- 如何将stdout重定向到stderr
- 编写时C++中的输入重定向问题
- 获取通过重定向传入的输入文件的名称?
- Windows C++重定向库
- 写入文件 a.txt,而终端重定向到文件 b.txt
- 使用 dup2() 进行输入重定向
- 将 clangd stderr 重定向到文件而不是控制台
- 如何在C++中获取重定向网页的URL
- 将标准输出重定向到ostream
- 如何撤消此代码上的 cin 重定向?
- 使用重定向标准处理子进程中的 kbhit
- 是否可以将子进程的 stdout 重定向到父进程中的另一个文件?
- 重定向输入和输出时如何处理主文件I/O?
- 如何将HTTPS流量重定向到本地主机:443上的代理?
- 使用重定向命令从 stdin 读入的字符串"<"输入文件未正确附加
- 尝试在 Windows 上重定向 stdout 和 stderr——_fileno(stdout) 返回 -2
- 可以将Boost消息队列文件重定向到用户指定的位置
- 在程序执行期间从标准输出重定向到自定义流
- 如何使用PHP将上传到本地主机的一个html文件重定向到磁盘上的另一个html文档
- 将CUDA PRINTF重定向到C 流