この質問は、SSE で __m128i ベクトルの最大値を取得しますか? に似ているようです。ただし、整数 + 最大の代わりに、短と最小を使用します。これは私が思いついたものです:
typedef short int weight;
weight horizontal_min_Vec4i(__m128i x) {
__m128i max1 = _mm_shufflehi_epi16(x, _MM_SHUFFLE(0, 0, 3, 2));
__m128i max1b = _mm_shufflelo_epi16(x, _MM_SHUFFLE(0, 0, 3, 2));
__m128i max2 = _mm_min_epi16(max1, max1b);
//max2 = _mm_min_epi16(max2, x);
max1 = _mm_shufflehi_epi16(max2, _MM_SHUFFLE(0, 0, 0, 1));
max1b = _mm_shufflelo_epi16(max2, _MM_SHUFFLE(0, 0, 0, 1));
__m128i max3 = _mm_min_epi16(max1, max1b);
max2 = _mm_min_epi16(max2, max3);
return min(_mm_extract_epi16(max2, 0), _mm_extract_epi16(max2, 4));
}
この関数は基本的に、x の上部と下部についてhttps://stackoverflow.com/a/18616825/1500111の回答と同じことを行います。したがって、最小値は __m128i 変数 max2 の位置 0 または 4 のいずれかにあることがわかっています。以下に示すSIMD 関数なしよりははるかに高速ですが 、最後の行horizontal_min_Vec4i_Plain(__m128i x)
がボトルネックになっていると思います。_mm_extract_epi16 operation
より良いスピードアップのために、これを達成するためのより良い方法はありますか? Haswell を使用しているので、最新の SSE 拡張機能にアクセスできます。
weight horizontal_min_Vec4i_Plain(__m128i x) {
weight result[8] __attribute__((aligned(16)));
_mm_store_si128((__m128i *) result, x);
weight myMin = result[0];
for (int l = 1; l < 8; l++) {
if (myMin > result[l]) {
myMin = result[l];
}
}
return myMin;
}