目前算法大多使用C语言开发,将算法移植到各种CPU平台时,由于各家编译器存在差异,经常会遇到MIPS性能问题。比如同样的C代码,不同的编译器优化结果会不同,导致在一个ARM上运行没问题的C代码换一个ARM芯片就可能存在性能问题。这时就需要将费时的C函数改成内联汇编指令。因此学一点汇编指令入门还是有必要的。本文讲解Speex使用x86的SSE指令优化乘加运算,代码在resample_sse.c。
#include <xmmintrin.h>
static inline float inner_product_single(const float *a, const float *b, unsigned int len)
{
int i;
float ret;
__m128 sum = _mm_setzero_ps();
/*
float sum = 0.0f;
for (i = 0; i < len; i ++)
{
sum += a[i] * b[i];
}
*/
for (i=0;i<len;i+=8)
{
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i), _mm_loadu_ps(b+i)));
sum = _mm_add_ps(sum, _mm_mul_ps(_mm_loadu_ps(a+i+4), _mm_loadu_ps(b+i+4)));
}
sum = _mm_add_ps(sum, _mm_movehl_ps(sum, sum));
sum = _mm_add_ss(sum, _mm_shuffle_ps(sum, sum, 0x55));
_mm_store_ss(&ret, sum);
return ret;
}
下面先逐个解释SSE指令的含义,再理解上述代码就不难了。
1、SSE支持浮点运算,VS2013已经集成SSE,包含头文件即可,具体如下。
mmintrin.h MMX
xmmintrin.h SSE
emmintrin.h SSE2
pmmintrin.h SSE3
tmmintrin.h SSSE3
intrin.h SSE4A
smmintrin.h SSE4.1
nmmintrin.h SSE4.2
2、__m128是128位(16字节)的数据类型,可以视为四个 32 位浮点元素a(a3, a2, a1, a0),下标从0到3,3是高位元素。_m128变量在16字节边界上自动对齐。VS2013调试器中显示如下图。
3、__m128 _mm_setzero_ps(void);清零指令,返回值r0 := r1 := r2 := r3 := 0.0
4、__m128 _mm_load_ps(float * p ); 加载指令,返回值r0 := p[0], r1 := p[1], r2 := p[2], r3 := p[3].
5、__m128 _mm_mul_ps(__m128 a , __m128 b ); 乘法指令,返回值r0 := a0 * b0, r1 := a1 * b1, r2 := a2 * b2,r3 := a3 * b3.
6、__m128 _mm_add_ps(__m128 a, __m128 b); 加法指令,返回值r0 := a0 + b0, r1 := a1 + b1, r2 := a2 + b2,r3 := a3 + b3.
__m128 _mm_add_ss(__m128 a , __m128 b ) ; 加法指令,返回值r0 := a0 + b0, r1 := a1, r2 := a2, r3 := a3.
SSE的浮点数运算指令分为两大类:packed和scalar。当后面的修饰符是_ps时,表示四个32位浮点数都执行加法运算,当后面的修饰符是_ss时,表示只对最低32位浮点数执行相关运算,高位保持不变。下图很清晰的作出解释。
7、__m128 _mm_movehl_ps( __m128 a, __m128 b );传送指令,将a和b的高位2个float组合得到新的__m128,返回值r3 := a3, r2 := a2, r1 := b3, r0 := b2.
8、__m128 _mm_shuffle_ps(__m128 a , __m128 b , int i );组合指令,shuffle翻译成中文有洗牌的意思。基于位置掩码i从a和b中选择特定元素构成返回值,掩码i可以使用宏_MM_SHUFFLE(z, y, x, w) (z<<6) | (y<<4) | (x<<2) | w计算。其中z, y说明返回值高位两元素使用b中哪个元素组成,x, w说明低位两元素使用a中哪个元素组成。例如:
9、void _mm_store_ss(float * p , __m128 a ); 存储指令,返回值*p := a0.
更多内容,请关注微信公众号“音频算法与工程实践”。