通过SSE加速矩阵乘法(C++)

Enz*_*nzo 12 c++ sse matrix-multiplication

我需要每秒运行240000次矩阵向量乘法.矩阵是5x5并且始终相同,而向量在每次迭代时都会发生变化.数据类型是float.我正在考虑使用一些SSE(或类似)指令.

1)我担心算术运算的数量与所涉及的存储器操作的数量相比太小.你认为我可以获得一些有形的(例如> 20%)改善吗?

2)我需要英特尔编译器吗?

3)你能指出一些参考文献吗?

谢谢大家!

Dir*_*tel 9

矢量,矩阵,...... 的Eigen C++模板库都有

  • 针对小型固定大小矩阵(以及动态大小的矩阵)的优化代码

  • 优化使用SSE优化的代码

所以你应该试一试.

  • 请注意,Eigen 文档声称它对于大小不是 16 字节倍数的固定向量表现不佳,因此它可能不会针对此问题自动进行向量化。我不能说 Eigen3 是否仍然如此。 (3认同)

小智 5

原则上,SSE 的加速可以是 4 倍(AVX 的 8 倍)。让我解释。

让我们称您为固定的 5x5 矩阵M。将 5D 矢量的分量定义为 (x,y,z,w,t)。现在从前四个向量 形成一个 5x4 矩阵U。

U =
xxxx
yyyy
zzzz
wwww
tttt
Run Code Online (Sandbox Code Playgroud)

接下来,做矩阵乘积MU = V。矩阵V包含M和前四个向量的乘积。唯一的问题是,对于 SSE,我们需要读取U的行,但在内存中U存储为xyzwtxyzwtxyzwtxyzwt所以我们必须将其转置为xxxxyyyyzzzzwwwwtttt。这可以通过 SSE 中的 shuffle/blends 来完成。一旦我们有了这种格式,矩阵乘积就会非常有效。

与使用标量代码进行 O(5x5x4) 操作不同,它只需要 O(5x5) 操作,即 4 倍加速。使用 AVX,矩阵U将是 5x8,因此它不会进行 O(5x5x8) 运算,而是只对 O(5x5) 征税,即 8 倍加速。

但是,矩阵V将采用xxxxyyyyzzzzwwwwtttt格式,因此根据应用程序,它可能必须转换为xyzwtxyzwtxyzwtxyzwt格式。

对接下来的四个向量(AVX 为 8 个)重复此操作,直到完成。

如果您可以控制向量,例如,如果您的应用程序动态生成向量,那么您可以以xxxxyyyyzzzzwwwwtttt格式生成它们并避免数组的转置。在这种情况下,您应该使用 SSE 获得 4 倍的加速,使用 AVX 获得 8 倍的加速。如果将此与线程(例如 OpenMP)结合使用,则使用 SSE 的加速应该接近 16 倍(假设有四个物理内核)。我认为这是你可以用 SSE 做的最好的事情。

编辑:由于指令级并行性 (ILP),您可以获得 2 倍的加速,因此 SSE 的加速可以在四核 (64x AVX) 下提高 32 倍,而由于 FMA3,Haswell 的加速又是 2 倍。