Rob*_*ert 9 c c++ parallel-processing
我只是想知道是否有任何有用的工具允许我在一些算法中利用指令级并行.更具体地说,我有一个来自多媒体领域的算法子集,我想知道在这个算法中利用ILP的最佳方法是什么.所有这些算法都是用C实现的,所以理想情况下我将这些算法作为输入提供给某个工具,它告诉我哪些指令可以并行执行.
非常感谢任何要点!
罗伯特
Goz*_*Goz 10
问题是考虑到有多少不同的处理器类型,决定是否并行执行指令是非常困难的.很好地理解您所针对的CPU架构将为您提供一个良好的起点来完成这类工作.没有软件会用正确的知识击败人类的思想.
一般来说,尽管编译器和乱序执行引擎之类的工作做了很多工作,但它试图尽可能多地抽象出来.你会发现,即使完全理解这一点,你也不可能获得超过百分之几的速度提升.
如果您希望看到严重的速度改进,那么重写算法以利用多个处理器和可用的SIMD操作要好得多.您可以单独使用SIMD看到严重的速度提升,对于许多可以同时处理多个数据元素的"多媒体算法"尤其如此.
首先,编译器和CPU本身都已经积极地重新排序指令以尽可能地利用ILP.最有可能的是,他们比你能做得更好.
但是,人类有一些可以帮助这一过程的领域.
编译器通常对重新排序浮点计算非常保守,因为它可能会稍微改变结果.所以例如假设这个代码:
float f, g, h, i;
float j = f + g + h + i;
Run Code Online (Sandbox Code Playgroud)
你可能得到零ILP,因为你编写的代码被评估为((f + g) + h) + i:第一次加法的结果被用作下一个的操作数,其结果在最后的加法中用作操作数.没有两个添加可以并行执行.
如果你不是把它写成float j = (f + g) + (h + i),该CPU能够执行f+g和h+i并行.他们不依赖于彼此.
通常,阻止ILP的是依赖性.有时它们是如上所述的算术指令之间的直接依赖关系,有时它们是存储/加载依赖关系.
与寄存器操作相比,加载和存储需要很长时间才能执行,依赖于这些操作的操作必须等到加载/存储操作完成.
因此,有时可以使用编译器可以在寄存器中缓存的临时存储数据来避免存储器访问.同样,尽快启动负载也有助于避免其延迟阻止以下操作.
最好的技术是密切关注您的代码,并找出依赖链.每个操作序列(其中每个操作依赖于前一个的结果)是一系列依赖项,它们永远不能并行执行.这条链可以以某种方式分解吗?也许通过将值存储在临时值中,或者可能通过重新计算值而不是等待从内存加载缓存版本.也许只是通过在原始浮点示例中放置一些括号.
当没有依赖关系时,CPU将调度操作以并行执行.因此,利用ILP所需要做的就是打破长依赖链.
当然,说起来容易做起来难... :)
但是如果你花了一些时间在分析器上,并研究编译器的汇编输出,你有时可以通过手动优化代码来获得令人印象深刻的加速,从而更好地利用ILP.