WebGL 或 CUDA 代码实际上是如何翻译成 GPU 指令的?
How is WebGL or CUDA code actually translated into GPU instructions?
当您在 WebGL 或 CUDA 中编写着色器等时,该代码实际上如何转换为 GPU 指令?
我想了解如何编写将图形渲染优化到极致的超底层代码,以便在 hardware/software 边界处准确查看 GPU 指令的执行方式。
我了解到,例如,对于 CUDA,您购买他们的显卡 (GPU),以某种方式实施以优化图形操作。但是,如果没有 C,您如何在此基础上(一般意义上)编程?
之所以问这个问题,是因为在previous question上,感觉GPU不能直接用汇编编程,所以有点迷糊。
如果您查看 CUDA by example 之类的文档,那只是 C 代码(尽管它们确实有 cudaMalloc
和 cudaFree
之类的东西,我不知道它们在做什么幕后)。但是在幕后,C 必须被编译为汇编或至少是机器代码或其他东西,对吧?如果是这样,那是如何访问 GPU 的?
基本上我没有看到在低于 C 或 GLSL 的级别上,GPU 本身是如何被指示执行操作的。你能解释一下吗?是否有一些程序集片段可以演示它是如何工作的,或者类似的东西?或者除了 x86 上的 16 "CPU registers" 之外,还有另一组某种 "GPU registers" 吗?
这些语言通过编译器翻译成机器代码。该编译器只是各种 API drivers/runtimes 的一部分,并且完全是特定于实现的。在 CPU 领域没有我们习惯的通用指令集系列——比如 x86、arm 或其他。不同的 GPU 都有自己的 incompatible 指令集。此外,这些 GPU 上没有可用于上传和 运行 任意二进制文件的 API。并且根据供应商的不同,几乎没有公开可用的文档。
The reason for this question is because on a previous question, I got the sense that you can't program the GPU directly by using assembly, so I am a bit confused.
好吧,你可以。理论上,至少。如果您不关心您的代码只能在一小部分 ASIC 上运行这一事实,并且如果您拥有所有必要的文档,并且如果您愿意实现一些 GPU 接口允许 运行 那些二进制文件,你可以做到。如果你想走那条路,你可以看看 Mesa3D project,因为它为许多 GPU 提供了开源驱动程序,包括一个基于 llvm 的编译器基础设施来为特定架构生成二进制文件。
在实践中,裸机大规模GPU编程没有有用的方法。
GPU 驱动程序将其编译为 GPU 可以理解的内容,这完全不同于 x86 机器代码。例如,下面是一段 AMD R600 汇编代码:
00 ALU: ADDR(32) CNT(4) KCACHE0(CB0:0-15)
0 x: MUL R0.x, KC0[0].x, KC0[1].x
y: MUL R0.y, KC0[0].y, KC0[1].y
1 z: MUL R0.z, KC0[0].z, KC0[1].z
w: MUL R0.w, KC0[0].w, KC0[1].w
01 EXP_DONE: PIX0, R0
END_OF_PROGRAM
其机器代码版本将由 GPU 执行。驱动程序协调将代码传输到 GPU 并指示它 运行 它。这都是特定于设备的,对于 nvidia,没有记录(至少没有正式记录)。
该片段中的 R0
是一个寄存器,但在 GPU 上,寄存器的工作方式通常有点不同。它们存在 "per thread",并且在某种程度上是共享资源(从某种意义上说,在一个线程中使用多个寄存器意味着更少的线程将同时处于活动状态)。为了让多个线程同时处于活动状态(这是 GPU 容忍内存延迟的方式,而 CPU 使用乱序执行和大缓存),GPU 通常有数万个寄存器。
当您在 WebGL 或 CUDA 中编写着色器等时,该代码实际上如何转换为 GPU 指令?
我想了解如何编写将图形渲染优化到极致的超底层代码,以便在 hardware/software 边界处准确查看 GPU 指令的执行方式。
我了解到,例如,对于 CUDA,您购买他们的显卡 (GPU),以某种方式实施以优化图形操作。但是,如果没有 C,您如何在此基础上(一般意义上)编程?
之所以问这个问题,是因为在previous question上,感觉GPU不能直接用汇编编程,所以有点迷糊。
如果您查看 CUDA by example 之类的文档,那只是 C 代码(尽管它们确实有 cudaMalloc
和 cudaFree
之类的东西,我不知道它们在做什么幕后)。但是在幕后,C 必须被编译为汇编或至少是机器代码或其他东西,对吧?如果是这样,那是如何访问 GPU 的?
基本上我没有看到在低于 C 或 GLSL 的级别上,GPU 本身是如何被指示执行操作的。你能解释一下吗?是否有一些程序集片段可以演示它是如何工作的,或者类似的东西?或者除了 x86 上的 16 "CPU registers" 之外,还有另一组某种 "GPU registers" 吗?
这些语言通过编译器翻译成机器代码。该编译器只是各种 API drivers/runtimes 的一部分,并且完全是特定于实现的。在 CPU 领域没有我们习惯的通用指令集系列——比如 x86、arm 或其他。不同的 GPU 都有自己的 incompatible 指令集。此外,这些 GPU 上没有可用于上传和 运行 任意二进制文件的 API。并且根据供应商的不同,几乎没有公开可用的文档。
The reason for this question is because on a previous question, I got the sense that you can't program the GPU directly by using assembly, so I am a bit confused.
好吧,你可以。理论上,至少。如果您不关心您的代码只能在一小部分 ASIC 上运行这一事实,并且如果您拥有所有必要的文档,并且如果您愿意实现一些 GPU 接口允许 运行 那些二进制文件,你可以做到。如果你想走那条路,你可以看看 Mesa3D project,因为它为许多 GPU 提供了开源驱动程序,包括一个基于 llvm 的编译器基础设施来为特定架构生成二进制文件。
在实践中,裸机大规模GPU编程没有有用的方法。
GPU 驱动程序将其编译为 GPU 可以理解的内容,这完全不同于 x86 机器代码。例如,下面是一段 AMD R600 汇编代码:
00 ALU: ADDR(32) CNT(4) KCACHE0(CB0:0-15)
0 x: MUL R0.x, KC0[0].x, KC0[1].x
y: MUL R0.y, KC0[0].y, KC0[1].y
1 z: MUL R0.z, KC0[0].z, KC0[1].z
w: MUL R0.w, KC0[0].w, KC0[1].w
01 EXP_DONE: PIX0, R0
END_OF_PROGRAM
其机器代码版本将由 GPU 执行。驱动程序协调将代码传输到 GPU 并指示它 运行 它。这都是特定于设备的,对于 nvidia,没有记录(至少没有正式记录)。
该片段中的 R0
是一个寄存器,但在 GPU 上,寄存器的工作方式通常有点不同。它们存在 "per thread",并且在某种程度上是共享资源(从某种意义上说,在一个线程中使用多个寄存器意味着更少的线程将同时处于活动状态)。为了让多个线程同时处于活动状态(这是 GPU 容忍内存延迟的方式,而 CPU 使用乱序执行和大缓存),GPU 通常有数万个寄存器。