5

320x240 の画像に縮小したい 8 ビットの 640x480 の画像があります。

void reducebytwo(uint8_t *dst, uint8_t *src)
//src is 640x480, dst is 320x240

ARM SIMD NEON を使用してそれを行う最善の方法は何でしょうか? どこかにサンプルコードはありますか?

出発点として、私は単に次のものと同等のことをしたいと思います:

for (int h = 0; h < 240; h++)
    for (int w = 0; w < 320; w++)
        dst[h * 320 + w] = (src[640 * h * 2 + w * 2] + src[640 * h * 2 + w * 2 + 1] + src[640 * h * 2 + 640 + w * 2] + src[640 * h * 2 + 640 + w * 2 + 1]) / 4; 
4

3 に答える 3

2

精度にあまり関心がない場合、この内側のループは、より正確なアルゴリズムと比較して 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) を使用して、受信データが必要になる前にキャッシュに引き上げる必要があります。

于 2013-08-07T12:09:12.477 に答える