2012-03-26 86 views
4

我试图将一些来自FANN Lib(用C语言编写的神经网络)的代码移植到SSE2中。 但是SSE2的性能比普通代码差。随着我的SSE2实施运行,一次运行需要5.50分钟而没有5.20分钟。sse2浮点乘法

SSE2如何比正常运行慢?难道是因为_mm_set_ps?我使用Apple LLVM Compiler(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]; 
+0

什么是'fann_mult'? – 2012-03-26 20:14:28

+6

如果你看一下装配体,它应该很清楚为什么它会变慢。您可能会惊讶于_mm_set_ps编译的内容。 (所以是的,你是在怀疑'_mm_set_ps'。) – Mysticial 2012-03-26 20:16:37

+0

sry。这只是一个定义。 #define fann_mult(x,y)(x * y) – 2012-03-26 20:16:52

回答

5

有你需要做以下这里看到了加速的任何机会:

  • 确保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%的速度。

+1

感谢您的回答。是的,有一个循环,我认为重组神经元很难,因为我不得不重写整个框架。 但总和水平+垂直的想法运作良好,我可以将性能提高到4.30米 – 2012-03-26 21:03:37

+1

@ user1293890 - 很高兴它有帮助 - *事后* SIMD优化,例如这可能是相当棘手,除非你准备做对相关数据结构进行大手术。 – 2012-03-26 21:06:06