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浮点乘法的主要内容,如果未能解决你的问题,请参考以下文章