我想学习使用英特尔Haswell CPU微体系结构的并行编程。 关于在asm / C / C ++ /(任何其他语言)中使用SIMD:SSE4.2,AVX2? 你能推荐书籍,教程,网络资源,课程吗?
谢谢!
答案 0 :(得分:27)
听起来我需要了解CPU上的并行编程。我在使用SSE,OpenMP或内在函数之前大约10个月前开始研究这个问题,所以让我简要总结一下我学到的一些重要概念和一些有用的资源。
可以采用多种并行计算技术: MIMD,SIMD,指令级并行,多级cahces和FMA 。有了Haswell,IGP也有计算。
我建议选择像矩阵乘法或Mandelbrot集这样的主题。他们都可以从所有这些技术中受益。
<强> MIMD 强>
通过MIMD我指的是使用多个物理核心进行计算。我建议使用OpenMP。阅读本教程 http://bisqwit.iki.fi/story/howto/openmp/#Abstract 然后将其用作参考https://computing.llnl.gov/tutorials/openMP/。使用MIMD的两个最常见的问题是race conditions和false sharing。定期关注OpenMP上的OpenMP。
<强> SIMD 强>
许多编译器都可以进行自动矢量化,所以我会研究一下。 MSVC的自动矢量化非常原始,但GCC非常好。
学习内在函数。了解内在函数的最佳资源是http://software.intel.com/sites/landingpage/IntrinsicsGuide/
另一个很棒的资源是Agner Fog的vectorclass。通过查看vectorclass的源代码,可以回答SSE / AVX上有关SO的95%的问题。最重要的是,你可以使用vectorclass进行大多数SIMD,并且仍然可以获得全速并跳过内在函数。
很多人使用SIMD效率低下。阅读有关结构数组(AOS)和数组结构(SOA)以及数组结构数组(AOSOA)的信息。另请参阅英特尔条带挖掘Calculating matrix product is much slower with SSE than with straight-forward-algorithm
有关在光线跟踪中实施SIMD的有趣方法,请参阅Ingo Wald's PhD thesis。我使用同样的想法让Mandelbrot设置使用SSE(AVX)一次计算4(8)个像素。
另请阅读Wald http://www.cdl.uni-saarland.de/papers/leissa_vecimp_tr.pdf撰写的“为便携式SIMD编程扩展C语言”这篇论文,以便更好地了解如何使用SIMD。
<强> FMA 强>
自Haswell以来,FMA3是新的。它是如此新颖,以至于尚未对SO进行过多讨论。但这个答案(对我的问题)是好的 How to use Fused Multiply-Add (FMA) instructions with SSE/AVX。 FMA3使峰值FLOPS加倍,因此与Ivy Bridge相比,Haswell的潜在矩阵乘法速度是其两倍。
根据this answer,FMA最重要的方面并不是它是一个指令而不是两个指令来进行乘法和加法,它是“(几乎)中间结果的无限精度”。例如,在没有FMA的情况下实现双倍乘法需要6次乘法和几次加法,而使用FMA则只需要两次操作。
指令级并行
Haswell有8个端口可以发送μ-ops(虽然不是每个端口都可以使用相同的mirco-op;请参阅此AnandTech review)。这意味着Haswell可以做到,例如two 256-bit loads, one 256-bit store, two 256-bit FMA operations, one scalar addition, and a condition jump at the same time(每个时钟周期6个op-ops)。
在大多数情况下,您不必担心这一点,因为它是由CPU完成的。但是,在某些情况下,您的代码可能会限制潜在的指令级并行性。最常见的是循环携带依赖。以下代码具有循环携带依赖性
for(int i=0; i<n; i++) {
sum += x(i)*y(i);
}
解决这个问题的方法是展开循环并进行部分求和
for(int i=0; i<n; i+=2) {
sum1 += x(i)*y(i);
sum2 += x(i+1)*y(i+1);
}
sum = sum1 + sum2;
多级缓存:
Haswell最多有四级缓存。在我看来,编写代码以最佳地利用缓存是迄今为止最困难的挑战。这是我仍然最挣扎并且感到最无知的话题,但在许多情况下,提高缓存使用率会比其他任何技术都提供更好的性能。我没有很多建议。
您需要了解关于页面的集合和缓存行(以及关键步幅)和NUMA系统。要了解关于集合和关键步幅的一点,请参阅Agner Fog http://www.agner.org/optimize/optimizing_cpp.pdf和Why is transposing a matrix of 512x512 much slower than transposing a matrix of 513x513?
缓存的另一个非常有用的主题是循环阻塞或平铺。以What is the fastest way to transpose a matrix in C++?为例,查看我的答案(评分最高的答案)。
在IGP上计算(使用Iris Pro)。
所有Haswell消费者处理器(Haswell-E尚未推出)都有IGP。 IGP使用至少30%的硅超过50%。这对于至少2个x86核心来说足够了。对于大多数程序员来说,这是浪费的计算潜力。编程IGP的唯一方法是使用OpenCL。英特尔没有针对Linux的OpenCL Iris Pro驱动程序,因此您只能使用Windows(我不确定Apple的实现有多好)。 Programming Intel IGP (e.g. Iris Pro 5200) hardware without OpenCL。
与Nvidia和AMD相比,Iris Pro的一个优点是双浮点仅为one quarter the speed of single floating point with the Iris Pro (however fp64 is only enabled in Direct Compute and not with OpenCL)。 NVIDIA和AMD(最近)瘫痪了双浮点,这使得GPGPU双浮点计算在他们的消费卡上不是很有效。