1

私は NEON 組み込み関数に頭を悩ませようとしており、例から始めていくつかの質問をすることができると考えました。

この実験では、32 ビット RGB を 16 ビット BGR に変換します。次のコードを NEON 組み込み関数を使用するように変換するには、まず何が良いでしょうか? ここで私が抱えている問題は、16 ビットが、私が見ることができる組み込みと一致しないことです。16x4 16x8 などがありますが、これにどのようにアプローチする必要があるかについて自分の考えをまとめる運がほとんどありません。任意のヒント?

これが私が変換しようとしているコードです。

typedef struct {
    uint16_t b:5, g:6, r:5;
} _color16;

static int depth_transform_32_to_16_c (VisVideo *dest, VisVideo *src)
{
    int x, y;
    int w;
    int h;

    _color16 *dbuf = visual_video_get_pixels (dest);
    uint8_t *sbuf = visual_video_get_pixels (src);

    uint16x8

    int ddiff;
    int sdiff;

    depth_transform_get_smallest (dest, src, &w, &h);

    ddiff = (dest->pitch / dest->bpp) - w;
    sdiff = src->pitch - (w * src->bpp);

    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            dbuf->b = *(sbuf++) >> 3;
            dbuf->g = *(sbuf++) >> 2;
            dbuf->r = *(sbuf++) >> 3;

            dbuf++;
            sbuf++;
        }

        dbuf += ddiff;
        sbuf += sdiff;
    }

    return VISUAL_OK;
}

編集: ああ、何らかの理由で 16x3 ビットを考慮してこれを見ていましたが、5,6,5 = 16 ビットを見ています。シフトが必要だと気づきました。うーん。

4

1 に答える 1

4

NEON は 128 ビット幅のレジスタを使用するため、概念的には、32 ビット RGB の 4 ピクセルを読み取り、それらに対してビット演算を使用し、最終的に 16 ビット ピクセルを書き出すことになります。1 つの観察結果として、最高のパフォーマンスを得るには、2 つの 128 ビット入力 (8 つの 32 ビット ピクセル) を組み合わせて、1 つの 128 出力を生成することができます。これにより、メモリアクセスがより効率的になります。

これについて考える別の方法は、内側のループ コンテンツを取得し、4 つのピクセルを並行して実行していることです。元のコードで作業するのが少し難しいのは、ビット フィールドを使用しているため、一部の「魔法」が隠されているためです。C コードを 32 ビットから 16 ビットで動作するように書き直し、シフトを使用した場合、および/またはそのコードはより自然に SIMD に変換され、そのコンテキスト内で複数のデータをどのように処理するかを視覚化できます。

各 32 ビット コンポーネント -> 16 ビット変換を見ると、次のようになります。

00000000RRRRRRRRGGGGGGGGBBBBBBBB
0000000000000000BBBBBGGGGGGRRRRR

これは、4 ピクセルに対して何を並行して行う必要があるかを視覚化するのに役立ちます。シフト、抽出、結合。これを 4 つの 32 ビット レーンと考えることができますが、一部のビット操作ではレジスタ幅は重要ではありません (たとえば、4 つの 32 ビット レジスタまたは 8 つの 16 ビット レジスタの論理和は同じです)。

大まかな擬似コード:

  • 読み取り (ベクトルロード) 128 ビット レジスタ = 4 32 ビット ピクセル。
  • 緑 (4 つのコンポーネントすべて) を右のビット位置にシフトします。
  • 緑を ( ANDマスクを使用して) 別のレジスターにマスクします。(概念的にはまだ 4x32 ビットの「モード」です)
  • 赤 (4 つのコンポーネントすべて) を右のビット位置にシフトします。
  • 赤をさらに別のレジスタにマスクします。
  • 青を右のビット位置にシフトします。
  • 青を別のレジスターにマスクアウトします。
  • 赤と青を右のビット位置にシフトします。
  • 結合するには、ビットごとのORを使用します。
  • これで、32 ビット アライメントの 4 つの 16 ビット値が得られます。(これまでのところ、概念的には 4x32 ビット)
  • 別の 4 ピクセルのセットで繰り返します。
  • これらの 2 つのセットを NEON unzip ( VUZP ) と組み合わせて、1 つの 128 ビット/8 ピクセル レジスタを生成します。
  • それらのピクセルを書き込みます (ベクトルストア)。
于 2012-02-26T19:02:58.980 に答える