【问题标题】:How does the host send OpenCL kernels and arguments to the GPU at the assembly level?主机如何在汇编级别向 GPU 发送 OpenCL 内核和参数?
【发布时间】:2020-10-09 00:58:45
【问题描述】:

所以你得到一个内核并编译它。您将cl_buffers 设置为参数,然后将clSetKernelArg 两者放在一起。

然后您将内核排入队列以运行并读回缓冲区。

现在,主机程序如何告诉 GPU 指令要运行。例如我正在使用带有 Radeon Pro 460 的 2017 MBP。在汇编级别,在主机进程中调用了哪些指令来告诉 GPU“这就是你要运行的内容”。什么机制可以让 GPU 读取cl_buffers?

事实上,如果你能指出我对所有这些的详细解释,我会非常高兴。我是一名工具链工程师,我对 GPU 编程的工具链方面很好奇,但我发现很难在上面找到好的资源。

【问题讨论】:

    标签: opencl gpu


    【解决方案1】:

    它几乎都通过 GPU 驱动程序运行。内核/着色器编译器等往往存在于用户空间组件中,但是当涉及到发布 DMA、内存映射和响应中断(GPU 事件)时,该部分至少在某种程度上被GPU 驱动程序的基于内核的组件。

    一个非常简单的解释是内核编译器生成一个特定于 GPU 模型的代码二进制文件,通过 DMA 将其上传到 VRAM,然后将请求添加到 GPU 的命令队列中以参考 VRAM 运行内核该内核的存储地址。

    关于 OpenCL 内存缓冲区,我认为基本上有 3 种方法可以实现:

    1. 缓冲区存储在 VRAM 中,当 CPU 需要访问它时,该范围的 VRAM 会映射到 PCI BAR,然后 CPU 可以对其进行内存映射以直接访问。
    2. 缓冲区完全存储在系统 RAM 中,当 GPU 访问它时,它使用 DMA 执行读取和写入操作。
    3. 缓冲区的副本同时存储在 VRAM 和系统 RAM 中; GPU 使用 VRAM 副本,CPU 使用系统 RAM 副本。每当一个处理器在另一个处理器对缓冲区进行修改后需要访问缓冲区时,就会使用 DMA 来复制较新的副本。

    在带有 UMA(Intel IGP、AMD APU、大多数移动平台等)的 GPU 上,VRAM 和系统 RAM 是相同的,因此它们基本上可以使用方法 1 和 2 的最佳部分。

    如果您想深入了解这一点,我建议您查看 Linux 上的开源 GPU 驱动程序。

    【讨论】:

      【解决方案2】:

      内核入队意味着要求 OpenCL 驱动程序将工作提交给专用硬件执行。例如,在 OpenCL 中,您将调用 clEnqueueNativeKernel API,它将调度计算工作负载命令添加到命令队列 - cl_command_queue。

      来自规范:

      命令队列可用于将一组操作(称为命令)按顺序排列。 https://www.khronos.org/registry/OpenCL/specs/2.2/html/OpenCL_API.html#_command_queues

      接下来,此 API 的实现将触发硬件处理记录到命令队列中的命令(该队列以特定硬件理解的格式保存所有实际命令)。硬件可能有多个队列并并行处理它们。无论如何,在处理来自队列的工作负载后,HW 将通过中断通知 KMD 驱动程序,KMD 负责通过 OpenCL 支持的事件机制将此更新传播到 OpenCL 驱动程序,这允许用户跟踪工作负载执行状态 - 参见https://www.khronos.org/registry/OpenCL/specs/2.2/html/OpenCL_API.html#clWaitForEvents .

      要更好地了解 OpenCL 驱动程序如何与硬件交互,您可以查看开源实现,请参阅: https://github.com/pocl/pocl/blob/master/lib/CL/clEnqueueNativeKernel.c

      【讨论】:

        猜你喜欢
        • 2011-10-05
        • 1970-01-01
        • 1970-01-01
        • 2017-09-11
        • 2012-02-05
        • 1970-01-01
        • 2020-10-07
        • 2013-04-07
        相关资源
        最近更新 更多