精度にあまり関心がない場合、この内側のループは、より正確なアルゴリズムと比較して 2 倍の計算スループットを提供するはずです。
for (i=0; i<640; i+= 32)
{
uint8x16x2_t a, b;
uint8x16_t c, d;
/* load upper row, splitting even and odd pixels into a.val[0]
* and a.val[1] respectively. */
a = vld2q_u8(src1);
/* as above, but for lower row */
b = vld2q_u8(src2);
/* compute average of even and odd pixel pairs for upper row */
c = vrhaddq_u8(a.val[0], a.val[1]);
/* compute average of even and odd pixel pairs for lower row */
d = vrhaddq_u8(b.val[0], b.val[1]);
/* compute average of upper and lower rows, and store result */
vst1q_u8(dest, vrhaddq_u8(c, d));
src1+=32;
src2+=32;
dest+=16;
}
vhadd
これは、入力と同じサイズの結果が得られる操作を使用して機能します。この方法では、最終的な合計を 8 ビットに戻す必要がなく、すべての演算が 8 ビットであるため、命令ごとに 2 倍の演算を実行できます。
ただし、中間合計が量子化され、GCC 4.7 がコードを生成するというひどい仕事をするため、精度は低くなります。GCC 4.8 は問題なく動作します。
ただし、操作全体が I/O バウンドになる可能性は十分にあります。ループは、ロードと演算の間の分離を最大化するために展開する必要があり、__builtin_prefetch()
(またはPLD
) を使用して、受信データが必要になる前にキャッシュに引き上げる必要があります。