从3D数学转换为SSE或者其他SIMD的速度提高了多少?

时间:2020-03-06 14:32:36  来源:igfitidea点击:

我在应用程序中广泛使用3D数学。通过将向量/矩阵库转换为SSE,AltiVec或者类似的SIMD代码,可以提高多少速度?

解决方案

我们很有可能只会看到非常小的加速(如果有的话),并且过程将比预期的更为复杂。有关更多详细信息,请参见Fabian Giesen撰写的Ubiquitous SSE向量类文章。

The Ubiquitous SSE vector class: Debunking a common myth
  
  Not that important
  
  First and foremost, your vector class is probably not as important for the performance of your program as you think (and if it is, it's more likely because you're doing something wrong than because the computations are inefficient). Don't get me wrong, it's probably going to be one of the most frequently used classes in your whole program, at least when doing 3D graphics. But just because vector operations will be common doesn't automatically mean that they'll dominate the execution time of your program.
  
  Not so hot
  
  Not easy
  
  Not now
  
  Not ever

这还不是全部,但是可以使用SIMD进行进一步的优化,看看Miguel关于他何时在MODC上举行的MONO实施SIMD指令的演讲,

在此特定配置中,SIMD击败了双打。 http://tirania.org/tmp/xpqetp.png

图片来自Miguel的博客条目。

答案很大程度上取决于库的功能以及使用方式。

增益可以从几个百分点上升到"快几倍",最容易看到增益的区域是那些我们不需要处理孤立的向量或者值,而必须处理多个向量或者值的区域。同样的方法。

另一个方面是当我们达到缓存或者内存限制时,这又需要处理大量的值/向量。

增益最大的领域可能是图像和信号处理,计算仿真以及对网格(而不是孤立的矢量)进行常规3D数学运算的领域。

如今,所有适用于x86的优秀编译器默认都会为SP和DP浮点运算生成SSE指令。使用这些指令几乎总是比本机指令快,即使是标量运算,只要我们正确地安排它们即可。这会让许多人感到惊讶,他们过去发现SSE速度很慢,并且认为编译器无法生成快速的SSE标量指令。但是现在,我们必须使用开关来关闭SSE生成并使用x87. 请注意,此时已不建议使用x87,并且可以将其从以后的处理器中完全删除。这样做的一个缺点是我们可能会失去在寄存器中执行80bit DP浮点的能力。但是共识似乎是,如果我们是依靠80位而不是64位DP浮点数来提高精度,则应该寻找一种具有更高精度的容差算法。

上面的一切让我感到完全惊讶。这很不直观。但是数据谈判。

对于一些非常粗糙的数字:我听说ompf.org上的一些人声称,某些手动优化的光线跟踪例程的速度提高了10倍。我也有一些不错的提速。我估计我的例行程序会根据问题在2到6倍之间,其中许多有一些不必要的存储和负载。如果代码中有大量分支,请不要理会,但是对于自然与数据并行的问题,我们可以做得很好。

但是,我要补充一点,算法应设计为数据并行执行。
这意味着,如果我们有一个如上所述的通用数学库,那么它应该使用打包向量而不是单个向量,否则我们将浪费时间。

例如。就像是

namespace SIMD {
class PackedVec4d
{
  __m128 x;
  __m128 y;
  __m128 z;
  __m128 w;

  //...
};
}

性能问题中的大多数问题都可以并行处理,因为我们很有可能正在使用大型数据集。对我来说,问题听起来像是过早优化的情况。

以我的经验,我通常会看到将算法从x87升级到SSE的性能提高了3倍,而使用VMX / Altivec的性能提高了5倍以上(因为复杂的问题与管道深度,调度等有关)。但是我通常只在有成百上千个数字需要处理的情况下才这样做,而不是针对那些我一次只做一个向量的情况。