我试图了解 OpenCL 编译器生成的机器代码以优化它。因此,我使用工具 m2s-opencl-kc(来自 multi2sim)离线编译我的 *.cl 文件并将中间文件(开关:-a)保留为 *.isa 文件。这个 *.isa 包含一个“反汇编”部分,这似乎是我正在寻找的......
注意:我的组装知识有点“老”。我为 Pentium 386/486 CPU 等老款 CPU 制作了组件。所以我实际上在阅读矢量指令时遇到了问题,而我对它们有一些理论知识。
[... OTHER STUFF ... ]
; -------- Disassembly --------------------
00 ALU_PUSH_BEFORE: ADDR(32) CNT(6) KCACHE0(CB2:0-15) KCACHE1(CB0:0-15)
0 x: MOV R2.x, 0.0f
z: SETGT_INT R0.z, 1, KC0[0].y
t: MULLO_INT ____, R1.x, KC1[1].x
1 w: ADD_INT ____, R0.x, PS0
2 y: ADD_INT R2.y, PV1.w, KC1[6].x
3 x: PREDE_INT ____, R0.z, 0.0f UPDATE_EXEC_MASK UPDATE_PRED
01 JUMP POP_CNT(1) ADDR(9)
02 ALU: ADDR(38) CNT(5) KCACHE0(CB1:0-15)
4 x: MOV R2.x, 0.0f
y: MOV R3.y, 0.0f
w: LSHL ____, R2.y, 2
5 z: ADD_INT R2.z, KC0[0].x, PV4.w
03 LOOP_DX10 i0 FAIL_JUMP_ADDR(8)
04 ALU: ADDR(43) CNT(11) KCACHE0(CB2:0-15)
6 y: ADD_INT R3.y, R3.y, 1
w: LSHL ____, R3.y, 2
7 x: SETGT_INT R3.x, KC0[0].y, PV6.y
z: ADD_INT ____, R2.z, PV6.w
w: ADD_INT ____, PV6.w, 8
8 x: ASHR R0.x, PV7.w, 4
y: LSHR R0.y, PV7.z, 2
z: BFE_UINT R0.z, PV7.w, 0x00000002, 0x00000002
[... some more ... ]
我想知道的是命令前面的数字和字符的含义。据我了解,编译器产生了一些“复杂”的指令:
00 ALU_PUSH_BEFORE: ADDR(32) CNT(6) KCACHE0(CB2:0-15) KCACHE1(CB0:0-15)
(问题:那是所谓的“非常长的指令词”吗?)
而这个“复杂”指令由多个“简单”指令组成:
0 x: MOV R2.x, 0.0f
z: SETGT_INT R0.z, 1, KC0[0].y
t: MULLO_INT ____, R1.x, KC1[1].x
1 w: ADD_INT ____, R0.x, PS0
2 y: ADD_INT R2.y, PV1.w, KC1[6].x
3 x: PREDE_INT ____, R0.z, 0.0f UPDATE_EXEC_MASK UPDATE_PRED
这些“简单”的指令似乎是每个向量单元的指令。四个向量单元由 x、y、z 和 w 引用。但什么是“不”?那是另一个向量单位吗?我为“赛普拉斯”GPU编译了它......
现在关于数字......这些就像“行号”吗?前导零:复杂指令序列号...?无前导零:简单指令序列号...?
如果我们假设内存访问没有等待状态,我假设所有具有相同序列的“简单”指令都可以在一个周期内“逻辑地”执行。例如,以下指令(上述复杂指令的)在周期 0 中“执行”:
0 x: MOV R2.x, 0.0f
z: SETGT_INT R0.z, 1, KC0[0].y
t: MULLO_INT ____, R1.x, KC1[1].x
“已执行”是指我们有某种(例如 4 周期)流水线。这意味着上述指令应该在周期 0 开始执行,并且应该在周期 3 之后完成。
关于流水线的问题
如果下一条指令(例如“1”)读取寄存器 R2.x 会发生什么?那会读取 R2.x 的旧值(在指令“0”之前)还是会延迟指令“1”,直到指令“0”完成?或者这可能是编译器必须注意的“不关心”情况(产生未定义的结果),这种情况永远不会发生?
关于内存访问的问题
我假设可以在数据获取周期期间执行对寄存器的访问,而无需等待。内存访问将需要一些额外的周期,具体取决于访问的内存类型:
- “__private”内存应该主要映射到寄存器。
- __local memory(最多 64KB 在同一组的工作项之间共享):在当前的 GPU 中我需要多少额外的周期?
- __global memory:这应该是例如 256MB 到 x GB 的外部 DRAM。我在这里需要多少额外的周期?据我所知,此内存没有为 GPU 设备缓存。
- __constant 内存应该类似于 __global 内存,但使用 __local 内存进行缓存
“ISA”有什么好的教程吗?
问候,斯特凡