HPC编程语言依赖于隐式向量化

时间:2016-02-01 10:13:49

标签: c opencl vectorization hpc

是否存在依赖于隐式矢量化的编程语言或语言扩展?

对于标量C代码的单/双精度的SSE4.1,AVX,AVX2(有或没有FMA3 / 4),我需要做出积极的假设来生成良好的DLP /向量化代码。

在过去的10年里,我依靠英特尔的内在函数来编写我的HPC内核,并明确地进行了矢量化。与此同时,我经常对C / C ++编译器(GCC,clang,LLVM等)生成的DLP代码的质量感到失望,如果你问,我可以发布具体的例子。

Intrinsics Guide开始,很明显手写"具有现代平台内在函数的HPC内核不再是可持续的选择,除非我有一大批程序员。太多版本和组合:SSE4.1,AVX,AVX2,AVX512 +口味,FMA,SP,DP,半精度?如果我的目标平台是2012年以来最普遍的平台,那就不可持续了。

我最近尝试过针对OpenCL(CPU)的英特尔离线编译器。我写了内核" la CUDA" (即标量代码,隐式矢量化),令我惊讶的是生成的程序集非常好地矢量化了! (Skylake,SP中的AVX2 + FMA)我遇到的唯一限制是缺少内置的数据缩减/互通通信功能而不依赖于共享内存(这将转换为CPU水平添加或shuffle + min / max操作)

正如clemens and sschuberth指出的那样,离线编译器并不是真正的解决方案,除非我不完全接受OpenCL。或者我破解我的调用者代码以遵守生成的程序集的调用约定,其中包括我不需要的参数,例如ndrange。完全接受OpenCL对我来说也不是一个选择,因为对于TLP我依赖于OpenMP和Pthreads(对于ILP,我依赖于硬件)。

更新

首先,值得回顾一下隐式矢量化和自动矢量化并不是一回事。事实上,我对自动向量化失去了希望(如上所述)。不在隐式向量化中。

以下答案之一是询问一些代码示例。 Here我提供了一个内核的代码示例,该内核实现了三维结构块上NSE对流项的三阶逆风方案。值得一提的是,这代表了一个简单的例子,因为不需要SIMD的通道间合作/通信。

2 个答案:

答案 0 :(得分:11)

英特尔SPMD程序编译器。

目前,最佳选择是Intel SPMD Program Compiler。 ISPC是一个开源编译器,其编程模型依赖于隐式向量化(借用英特尔OpenCL SDK文档的术语)来输出向量化汇编代码。 ISPC将源代码映射到SPE / SS的SSE4.1,AVX,AVX2,KNC和KNL的AVX512指令。 ISPC的后端是LLVM。

对于CFD内核,它只提供无与伦比的性能。对于必须是标量的代码部分,只需添加" uniform"关联变量的关键字。有一些用于车道间通信的内置功能,如shuffle,broadcast和reduce_add等。

为什么ISPC与其他C ++编译器相比如此之快? 我的猜测是因为C / C ++编译器假设没有任何东西可以被矢量化,除非有明确的相反证据。除非另有说明,ISPC假定所有SIMD通道都(独立地)执行每行代码。

我想知道为什么ISPC尚未被广泛接受。 也许是因为他的少年阶段,但它在CG /科学可视化社区中已经表现出很强的能力(EmbreeOSPray)。 ISPC是编写HPC内核的一个很好的选择,因为它似乎很好地弥合了性能 - 生产力差距。

基准

对于问题中引用的trivial kernel example,使用GCC 4.9.X和ISPC 1.8.2获得以下结果。根据每个周期的FLOP报告性能。

enter image description here

此处未报告ICC结果(就可访问性而言,向ICC报告免费和开源编译器是否100%公平?)。尽管如此,在这种情况下,ICC相对于GCC报告的最大增益约为4倍,因此不会影响ISPC的优势。

答案 1 :(得分:7)

请注意,如果没有数学或代码示例,很难知道这里的最佳答案是什么。如果您提供代码示例,我将尝试使用下面提到的一些方言来实现它。

Fortran 90

Fortran 90+冒号表示法是实现隐式向量化的好方法,但我怀疑如果你是C内在函数程序员,Fortran不是你愿意使用的东西。

有关此主题的一个合理信息来源是fortran90.org

OpenMP 4.0

OpenMP 4.0引入了SIMD关键字,它强制编译器对代码进行矢量化。您应该将其作为内在函数的替代方案。

OpenMP 4.0 pragma omp simd在线有很多例子,但非常简单的例子是Enabling SIMD in program using OpenMP4.0

显然,OpenMP的最终权限是最新的说明:OpenMP Application Programming Interface Version 4.5

CilkPlus

由于您已经表示愿意编写低于ISO标准的代码,因此您可能愿意使用CilkPlus对C / C ++的扩展,以支持英特尔编译器和GCC(以及可能的Clang / LLVM,但我还没有验证过。)

有关详细信息,请参阅Best practices for using Intel® Cilk™ Plus CilkPlus home page

的OpenCL

OpenCL在理论上是另一个不错的选择,但在实践中似乎不太引人注目。我自己不是OpenCL用户,但我与OpenCL Programming Guide的作者合作,我认为他是一个可靠的来源。

自动向量化

如果所有其他方法都失败了,那么英特尔16编译器可以很好地实现自动向量化,但您必须阅读选择报告,在许多情况下使用restrict__assume_aligned

尝试使用Intel C / C ++实现自动向量化时,最好的起点是-qopt-report编译器选项。这通常会告诉你什么是矢量化而不是,为什么。您可能需要使用不同的分配器(Why use _mm_malloc? (as opposed to _aligned_malloc, alligned_alloc, or posix_memalign)列出相关选项),然后在内核中使用__assume_aligned。如果您使用第二代英特尔至强融核处理器(又称Knights Landing)或其他支持它们的产品,AVX-512CDI instructions可能有所帮助,那么矢量依赖可能更难以缓解。

Cray编译器也可以自动进行自动向量化,但仅限于有权访问Cray超级计算机的用户。

对于那些好奇的人,我对这些编译器的乐观主要基于NWChem kernels获得的结果。使用Fortran 77,OpenMP 3/4以及使用其他编译器指令可以获得最佳结果,但至少在那里没有特定于处理器的代码。并且C99内核的矢量化足够好。

声明

我在英特尔从事研究/寻路工作。我不使用任何软件产品,但我不时向编译器团队的专家学习。