从Linux内核的角度来看,用户程序如何与CUDA GPU通信?

从Linux内核的角度来看,用户程序如何与CUDA GPU通信?

我很好奇当我运行 CUDA 程序时,数据如何在 CPU 和 GPU 内存之间来回复制。具体来说,我想知道Linux内核是如何参与这个过程的。

我有一些可能的假设:

  1. CUDA 用户库将 GPU 视为一个文件,read(2)write(2)为每个事务调用 和 。
  2. CUDA 用户库要求 Linux 将mmap(2)相关控制寄存器(DMA 寄存器、PIO 寄存器和其他一些 MMIO 寄存器)放入用户空间,然后在用户态下对 GPU 进行任意操作。
  3. 还有别的事吗?

我通过运行简单的 CUDA 程序来消除假设#1,该程序来回复制数据 1000 次(并在其间启动一些空内核),其中strace(1)没有观察到对write(2)和 的任何调用read(2)

假设 #2 似乎是可能的,因为我观察到time(1)传输的数据量似乎随着user时间而不是sys时间而变化。所以该程序似乎是在用户态复制数据。

但似乎有点奇怪。如何允许用户程序自己操作如此重要的I/O控制寄存器?

我将不胜感激有关这个主题的一些专业想法。

答案1

应用程序在启动时向内核请求mmap一组缓冲区,创建此映射是一项特权操作。

正常操作只是用数据(例如纹理、顶点或命令)填充这些缓冲区,最后进行单个内核调用来启动提交的命令队列。此启动选通是唯一执行的寄存器访问,其他所有内容都是共享内存。

GPU 有自己的基本 MMU,以确保命令无法引用属于另一个上下文的数据,除非需要(例如,将游戏中的渲染目标与覆盖层中的渲染目标组合在一起的合成器,并将结果写入到本地)屏幕缓冲区)。

对于仅计算的工作负载,相同的机制可以正常工作,命令队列只是不以“将数据发送到屏幕”结束,而是以“将数据返回到主机”结束。

相关内容