2015-10-31 32 views
8

optimization guide of Beignet, an open source implementation of OpenCL targeting Intel GPUs如何充分利用OpenCL中的SIMD?

工作组大小应大于16和是多个的16

作为根上两个可能的SIMD通道是8或16。为了不浪费SIMD 车道,我们需要遵循这个规则。

Compute Architecture of Intel Processor Graphics Gen7.5还提到:

对于基于Gen7.5产品,每个EU有七个线程总共通用寄存器文件的28千字节(GRF)。

...

在Gen7.5计算架构,最SPMD编程模型采用 这种风格的代码生成和欧盟的处理器执行。实际上, 每个SPMD内核实例似乎在其自己的SIMD通道中串行且独立地执行。

实际上,每个线程同时执行一个SIMD宽度的内核实例数。 因此,对于计算 内核的SIMD-16编译,可能的是SIMD-16×7个=线程112个内核实例 是在单个EU同时执行。类似地,对于SIMD-32 x 7个线程= 224个内核实例在单个的 EU上同时执行。

如果我正确理解它,使用SIMD-16 x 7 threads = 112 kernel instances作为示例,为了在一个EU运行224个螺纹,工作组大小需要是16。然后OpenCL编译器将折叠16个内核实例为16 SIMD线程,并在7个工作组上执行7次,并在单个EU上运行它们?

问题1:我是否正确?

但是OpenCL spec也提供矢量数据类型。因此,通过传统的SIMD编程(如NEON和SSE)充分利用EU中的SIMD-16计算资源是可行的。

问题2:如果是这种情况,使用vector-16数据类型已经明确使用SIMD-16资源,因此删除了每工作组至少16个项目的限制。是这样吗?

问题3:如果以上为真,那么如何两个方法相互比较:1) 112螺纹折叠成由OpenCL编译7 SIMD-16线程; 2) 7个原生线程编码为明确使用vector-16数据类型和SIMD-16操作?

回答

1
  1. 差不多。您正在假设每个工作组有一个线程(在此上下文中的N.B.线程是CUDA称为“wave”的线程。在英特尔GPU中,说一个工作项目是GPU线程的SIMD通道)。如果没有子组,则无法强制工作组大小完全成为线程。例如,如果选择WG大小为16,编译器仍然可以自由地编译SIMD8并将其分布在两个SIMD8线程中。请记住,编译器在WG大小已知之前选择SIMD宽度(clCompileProgramclEnqueueNDRange之前)。 subgroups extension可能会允许您强制SIMD宽度,但绝对不会在GEN7.5上实现。

  2. OpenCL矢量类型是一个可选的显式矢量化步骤,在已经自动发生的隐式矢量化之上。例如,您是否使用float16。每个工作项都将处理16个浮点数,但编译器仍然会编译至少SIMD8。因此,每个GPU线程将处理(8 * 16)浮动(尽管并行)。这可能有点矫枉过正。理想情况下,我们不希望通过使用明确的OpenCL矢量类型来明确地向量化我们的CL。但是如果内核没有做足够的工作(内核太短可能会很糟糕),它可能会有所帮助。某处说float4是一个很好的经验法则。

  3. 我想你的意思是112个工作项目?通过本地线程你是指CPU线程还是GPU线程?

    • 如果你指的是CPU线程,那么关于GPU的常用参数就适用。当你的程序没有太多差异时(所有的实例采用相似的路径),并且你使用足够多的时间来减少传输GPU和GPU的成本(算术密度)时,GPU是很好的。
    • 如果你的意思是GPU线程(GEN SIMD8或SIMD16生物)。目前没有(公开可见的)方式来明确编程GPU线程(编辑请参阅subgroups extension(在GEN7.5上不可用))。如果你能够做到的话,它会和汇编语言相似。工作比较困难,编译器有时会比我们做得更好,但是当您解决特定问题并获得更好的领域知识时,通常可以通过足够的编程工作做得更好(直到硬件更改和聪明的程序假设变为无效)