官术网_书友最值得收藏!

1.1.1 算術運算

SSE內置函數中支持的算術操作如表1-1所示。從表中可以看出,SSE幾乎支持所有常用的算術運算。故可以預知:大多數算法只要滿足向量化數據并行的特點,就有可能能夠使用SSE指令進行向量化。

表1-1 SSE算術運算

表1-1中有一些不太常見的指令,本節簡要介紹一些。

hadd表示將一個向量相鄰的兩個元素相加,并要保持原來的向量大小。因此它具有兩個參數,如下例所示:


__m128 _mm_hadd_ps(__m128 a, __m128 b);
r[0] = a[0]+a[1];
r[1] = a[2]+a[3];
r[2] = b[0]+b[1];
r[3] = b[2]+b[3];
__m128 _mm_addsub_ps(__m128 a, __m128 b);
r[0] = a[0]-a[1];
r[1] = a[2]+a[3];
r[2] = b[0]-b[1];
r[3] = b[2]+b[3];

其中:r表示結果,使用數組表示法就是表示向量中的第幾個元素,如[2]表示其為向量寄存器中保存的第三個元素。

使用hadd能夠比較容易地實現多個向量求內積,如代碼清單1-1所示。

代碼清單1-1 使用hadd求向量內積


__m128 a = _mm_mul_ps(b, c);
__m128 zero = _mm_setzero_ps();
a = _mm_hadd_ps(a, zero);
a = _mm_hadd_ps(a, zero);

運算完成后,a中的第一個元素即為b、c兩個向量的內積。

其實addsub應該寫作subadd,因為第一個操作是減法。hsub和hadd類似,只是執行的運算是減法。

比較有意思的是dp操作,對于單精度浮點類型的數據,其定義如下:


__m128 _mm_dp_ps(__m128 a, __m128 b, const int mask);
__m128 tmp;
tmp[0] = (mask[4]==1) ? (a[0]*b[0]) : 0.0;
tmp[1] = (mask[5]==1) ? (a[1]*b[1]) : 0.0;
tmp[2] = (mask[6]==1) ? (a[2]*b[2]) : 0.0;
tmp[3] = (mask[7]==1) ? (a[3]*b[3]) : 0.0;
__mm32 tmp4
tmp4 = tmp[0] + tmp[1] + tmp[2] + tmp[3];
r[0] = (mask[0]==1) ? tmp4 : 0.0;
r[1] = (mask[1]==1) ? tmp4 : 0.0;
r[2] = (mask[2]==1) ? tmp4 : 0.0;
r[3] = (mask[3]==1) ? tmp4 : 0.0;

很明顯,一條dp操作可以直接實現兩個向量的內積運算,如代碼清單1-2所示。

代碼清單1-2 使用dp操作實現兩個向量的內積運算


int mask = 1+(1<<4)+(1<<5)+(1<<6)+(1<<7);
__m128 r = _mm_dp_ps(b, c, mask);

blend和blendv操作類似于C/C++中的三目運算符(?:),blend依據掩碼的位選擇,而blendv依據掩碼向量中各元素的符號位選擇,示例如下:


__m128 _mm_blend_ps(__m128 a, __m128 b, const int mask);
r[0] = (mask[0]==0) ? a[0] : b[0];
r[1] = (mask[1]==0) ? a[1] : b[1];
r[2] = (mask[2]==0) ? a[2] : b[2];
r[3] = (mask[3]==0) ? a[3] : b[3];
__m128 _mm_blendv_ps(__m128 a, __m128 b, __m128 mask);
r[0] = (mask[0]&0x80000000) ? b[0] : a[0];
r[1] = (mask[1]&0x80000000) ? b[1] : a[1];
r[2] = (mask[2]&0x80000000) ? b[2] : a[2];
r[3] = (mask[3]&0x80000000) ? b[3] : a[3];

很容易想到,可以使用blendv向量化一些簡單的分支運算,如代碼清單1-3所示。

代碼清單1-3 簡單的可向量化的分支運算示例


for(int i = 0; i < n; i++){
        r[i] = a[i] > 0 ? b[i]:c[i];
}

這同時要求許多比較指令返回結果的符號位為0或1。

主站蜘蛛池模板: 蒙阴县| 东兴市| 瑞安市| 桐庐县| 永定县| 南郑县| 潮州市| 满洲里市| 邓州市| 余庆县| 镇安县| 额敏县| 汶上县| 阆中市| 临洮县| 新竹县| 汾西县| 昌平区| 镇赉县| 尼玛县| 屏山县| 长沙县| 驻马店市| 八宿县| 中江县| 吉木乃县| 新乐市| 祁连县| 砚山县| 三台县| 栾城县| 建宁县| 巩留县| 兴安县| 民勤县| 连城县| 文安县| 霸州市| 永吉县| 富裕县| 大洼县|