利用SSE计算向量点乘simd_dot

2017-08-31 12:45:36来源:CSDN作者:fuwenyan人点击

分享

本博记录为卤煮理解,如有疏漏,请指正。转载请注明出处。

卤煮:非文艺小燕儿

本博地址:利用SSE计算向量点乘simd_dot


所谓SSE(Streaming SIMD Extensions),也就是单指令多数据流的扩展。所谓单指令多数据流呢,简单理解就是多个数据流同时处理一条指令。

举个栗子:

一个水箱中的水,底部开1个洞放水,就是单指令单数据流。底部同时开多个相同大小的洞放水,就是单指令多数据流。

多个洞放水当然会比1个洞放得快啦,也就是同样的指令,多数据流速度就快呀。


对于SSE,其实就是处理器中专门开辟了多个128位的寄存器。对于单精度浮点数,占用32bit,那么1个128bit的SSE寄存器,就可以存放4个单精度浮点数。对于单精度浮点数的运算指令,其实就相当于开了4个洞。比如,两个128位的SSE寄存器中存放的数据进行乘法运算,那么一次性就能得到4组运算结果。


大概就是这么个意思。接下来就对采用SSE优化的向量点乘进行详细注释说明。

输入x和y都是长度为len的向量。我们要求x.*y,并将结果返回。


float simd_dot(const float* x, const float* y, const long& len) {	float inner_prod = 0.0f;	__m128 X, Y; //声明两个存放在SSE的128位专用寄存器的变量	__m128 acc = _mm_setzero_ps(); // 声明一个存放在SSE的128位专用寄存器的变量,用来存放X+Y的结果,初始值为0	float temp[4];//存放中间变量的参数	long i;	for (i = 0; i + 4 < len; i += 4) {//128位专用寄存器,一次性可以处理4组32位变量的运算		X = _mm_loadu_ps(x + i); // 将x加载到X(由于128位可以存放四个32位数据,所以默认一次加载连续的4个参数)		Y = _mm_loadu_ps(y + i);//同上		acc = _mm_add_ps(acc, _mm_mul_ps(X, Y));//x*y,每轮的x1*y1求和,x2*y2求和,x3*y3求和,x4*y4求和,最终产生的四个和,放在acc的128位寄存器中。	}	_mm_storeu_ps(&temp[0], acc); // 将acc中的4个32位的数据加载进内存	inner_prod = temp[0] + temp[1] + temp[2] + temp[3];//点乘求和	// 刚才只是处理了前4的倍数个元素的点乘,如果len不是4的倍数,那么还有个小尾巴要处理一下	for (; i < len; ++i) {		inner_prod += x[i] * y[i];//继续累加小尾巴的乘积	}	return inner_prod;//大功告成}



微信扫一扫

第七城市微信公众平台