sse2浮点乘法

Posted

技术标签:

【中文标题】sse2浮点乘法【英文标题】:sse2 float multiplication 【发布时间】:2012-03-26 20:12:06 【问题描述】:

我尝试将一些代码从 FANN Lib(用 C 编写的神经网络)移植到 SSE2。 但是 SSE2 的性能比普通代码差。使用我的 SSE2 实现运行一次运行需要 5.50 分钟而不需要 5.20 分钟。

SSE2 怎么会比正常运行慢?难道是因为_mm_set_ps?我使用 Apple LLVM 编译器 (XCode 4) 编译代码(所有 SSE 扩展标志都打开,优化级别为 -Os)。

没有 SSE2 的代码

                neuron_sum +=
                fann_mult(weights[i], neurons[i].value) +
                fann_mult(weights[i + 1], neurons[i + 1].value) +
                fann_mult(weights[i + 2], neurons[i + 2].value) +
                fann_mult(weights[i + 3], neurons[i + 3].value);

SSE2 代码

                __m128 a_line=_mm_loadu_ps(&weights[i]);
                __m128 b_line=_mm_set_ps(neurons[i+3].value,neurons[i+2].value,neurons[i+1].value,neurons[i].value);
                __m128 c_line=_mm_mul_ps(a_line, b_line);
                neuron_sum+=c_line[0]+c_line[1]+c_line[2]+c_line[3];

【问题讨论】:

如果您查看程序集,应该很清楚为什么它变慢了。您可能会对 _mm_set_ps 编译成的内容感到惊讶。 (所以是的,你怀疑_mm_set_ps 是对的。) 对不起。这只是一个定义。 #define fann_mult(x,y) (x*y) 相关:***.com/questions/4120681/… 【参考方案1】:

为了有机会在这里看到加速,您需要执行以下操作:

确保weights[i] 是16 字节对齐的,然后使用_mm_load_ps 而不是_mm_loadu_ps 重组 neurons[] 使其成为 SoA 而不是 AoS(也是 16 字节对齐),然后使用 _mm_load_ps 一次加载 4 个值 将水平和移出循环(有一个循环,对吗?) - 只需将 4 个部分和保留在向量 vneurom_sum 中,然后在循环后对该向量进行最终水平和

即便如此,您也不会看到显着的加速,因为您只对 2 次加载和 1 次存储执行一次算术运算。由于大多数现代 x86 CPU 无论如何都有两个标量 FPU,因此您可能不会接近 128 位浮点 SIMD 的理论 4 倍加速,我预计相对于标量代码的速度不会超过 50%。

【讨论】:

感谢您的回答。是的,有一个循环,我认为重组神经元会很困难,因为我必须重写整个框架。但是水平+垂直总和的想法效果很好,我可以将性能提高到 4.30m @user1293890 - 很高兴它有所帮助 - 事后 SIMD 优化这样的可能非常棘手,除非您准备对相关数据结构进行大手术。跨度>

以上是关于sse2浮点乘法的主要内容,如果未能解决你的问题,请参考以下文章

你如何在 SSE2 上进行带符号的 32 位扩展乘法?

向量矩阵乘法、浮点向量、二进制矩阵

Verilog中的浮点乘法问题

JS 乘法运算出现了浮点,该怎么解决

间接成本 ~ 浮点乘法的 3 倍,真的吗? (带演示)

是否允许编译器优化浮点常量乘法