总结:您的加速有点复杂,但是您的机器(英特尔 GPU,可能是 GEN8 或 GEN9)的 fp32 吞吐量 768 每个 (GPU) 时钟的 FLOP 和 fp16 的 1536。让我们假设 fp32,所以小于 768x(可能是其中的三分之一,取决于 CPU 速度)。有关推理和一些非常重要的注意事项,请参见下文。
关于 CL_DEVICE_MAX_COMPUTE_UNITS 的简短说明:
英特尔在其 GPU 驱动程序中使用 CL_DEVICE_MAX_COMPUTE_UNITS 时会做一些奇怪的事情。
来自clGetDeviceInfo (OpenCL 2.0)。 CL_DEVICE_MAX_COMPUTE_UNITS 说
OpenCL 设备上的并行计算单元数。一种
工作组在单个计算单元上执行。最小值为 1。
但是,英特尔显卡驱动程序实际上并未遵循此定义,而是返回 EU(执行单元)的数量 --- 一个 EU,一组 SIMD ALU 和插槽用于 7 个不同的 SIMD 线程(寄存器等) .每个 SIMD 线程代表 8、16 或 32 个工作项,具体取决于编译器选择的内容(我们想要更高,但寄存器压力会迫使我们降低)。
一个工作组实际上仅限于一个“切片”(see the figure in section 5.5 "Slice Architecture"),恰好是 24 个 EU(在最近的硬件中)。选择 GEN8 或 GEN9 文档。每个切片都有自己的 SLM、障碍和 L3。鉴于您的 Apple Book 报告了 48 个 EU,我会说您有两个部分。
最大加速:
让我们忽略这个主要的烦恼并使用欧盟编号(以及上面的那些拱文档)。对于“加速”,我正在比较 CPU 上的单线程 FP32 计算。如果 CPU 具有良好的并行化等,当然加速会更少。
在理想情况下,48 个 EU 中的每一个都可以在每个时钟发出两个 SIMD4 操作。假设这些是融合的乘加(实际上是两个操作),这给了我们:
48 EUs * 2 SIMD4 ops per EU * 2 (if the op is a fused multiply add)
= 192 SIMD4 ops per clock
= 768 FLOPs per clock for single precision floating point
所以你理想的加速实际上是 ~768。但是有很多东西可以计算出这个理想的数字。
- 设置和拆卸时间。让我们忽略这一点(假设 WL 时间支配运行时)。
- GPU 时钟最高可达千兆赫,而 CPU 运行速度更快。将该比率考虑在内。(大概是 1/3?CPU 上 3Ghz 与 GPU 上 1Ghz)。
- 如果计算不是大量乘加“疯狂”,则除以 2,因为我在上面加倍。但是,许多重要的工作负载都是“疯狂”的。
- 执行大部分是非发散的。如果 SIMD 线程分支为 if-then-else,则整个 SIMD 线程(8、16 或 32 个工作项)都必须执行该代码。
- 注册银行冲突延迟会降低 EU ALU 吞吐量。通常,编译器会很好地避免这种情况,但理论上它会稍微影响您的性能(通常取决于寄存器压力的几个百分点)。
- 缓冲区地址计算也可以减少几个百分点(EU 必须花时间进行整数计算以读取和写入地址)。
- 如果使用过多的 SLM 或障碍,GPU 必须让一些 EU 空闲,以便机器上的每个工作项都有足够的 SLM。 (您可以调整算法来解决此问题。)
- 我们必须保持 WL 计算绑定。如果我们炸毁数据访问层次结构中的任何缓存,我们就会遇到没有线程准备好在 EU 上运行并且必须停止的情况。假设我们避免这种情况。
?.我可能忘记了其他可能出错的事情。
我们称效率为理论完美的百分比。因此,如果我们的工作负载以每时钟约 530 FLOPs 运行,那么我们的效率是理论 768 的 60%。我已经看到非常仔细调整的工作负载效率超过 90%,但它肯定需要一些工作。