這是使用SSE3內部函數執行請求的操作的示例。輸入和輸出指針必須是16字節對齊的,並且一次對16個像素塊進行操作。
雖然我不認爲你會得到顯着的提速。對像素執行的操作非常簡單,以至於內存帶寬占主導地位。
#include <tmmintrin.h>
/* in and out must be 16-byte aligned */
void rgb_to_bgrx_sse(unsigned w, const void *in, void *out)
{
const __m128i *in_vec = in;
__m128i *out_vec = out;
w /= 16;
while (w-- > 0) {
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
* in_vec[0] Ra Ga Ba Rb Gb Bb Rc Gc Bc Rd Gd Bd Re Ge Be Rf
* in_vec[1] Gf Bf Rg Gg Bg Rh Gh Bh Ri Gi Bi Rj Gj Bj Rk Gk
* in_vec[2] Bk Rl Gl Bl Rm Gm Bm Rn Gn Bn Ro Go Bo Rp Gp Bp
*/
__m128i in1, in2, in3;
__m128i out;
in1 = in_vec[0];
out = _mm_shuffle_epi8(in1,
_mm_set_epi8(0xff, 9, 10, 11, 0xff, 6, 7, 8, 0xff, 3, 4, 5, 0xff, 0, 1, 2));
out = _mm_or_si128(out,
_mm_set_epi8(0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0));
out_vec[0] = out;
in2 = in_vec[1];
in1 = _mm_and_si128(in1,
_mm_set_epi8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0));
out = _mm_and_si128(in2,
_mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
out = _mm_or_si128(out, in1);
out = _mm_shuffle_epi8(out,
_mm_set_epi8(0xff, 5, 6, 7, 0xff, 2, 3, 4, 0xff, 15, 0, 1, 0xff, 12, 13, 14));
out = _mm_or_si128(out,
_mm_set_epi8(0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0));
out_vec[1] = out;
in3 = in_vec[2];
in_vec += 3;
in2 = _mm_and_si128(in2,
_mm_set_epi8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0));
out = _mm_and_si128(in3,
_mm_set_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
out = _mm_or_si128(out, in2);
out = _mm_shuffle_epi8(out,
_mm_set_epi8(0xff, 1, 2, 3, 0xff, 14, 15, 0, 0xff, 11, 12, 13, 0xff, 8, 9, 10));
out = _mm_or_si128(out,
_mm_set_epi8(0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0));
out_vec[2] = out;
out = _mm_shuffle_epi8(in3,
_mm_set_epi8(0xff, 13, 14, 15, 0xff, 10, 11, 12, 0xff, 7, 8, 9, 0xff, 4, 5, 6));
out = _mm_or_si128(out,
_mm_set_epi8(0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0, 0, 0));
out_vec[3] = out;
out_vec += 4;
}
}
您是否使用了編譯器的優化標誌(哪一個?)?編譯器通常會更好地優化代碼,而不會引入錯誤。你收集了哪些基準數據? –
不是SSE的答案,但你有沒有嘗試展開你的循環4次,使得輸入總是從一個對齊的地址開始?然後,您可以逐字讀取輸入的機器字,並針對源像素的每個相對位置使用專門的移位和掩碼。正如Dana提到的那樣,值得一看的是編譯器在高優化級別上執行得如何(除了基準測試之外還檢查生成的彙編代碼),但是我懷疑它是否足夠積極展開循環_並且根據「in」全部由它自己對齊。 –
偉大的問題。它只是「O2」(不是O3)和GCC4.6。我的基準情況是以512作爲「寬度」跨度的10K迭代運行。感謝您的好評! – Rev316