1

学術的な目的で、次のアルゴリズムの ARM NEON 最適化を記述して、パフォーマンスの向上が得られるかどうかをテストしたいと思います。結果がマージされて並列化の利点が失われるため、これは SIMD 最適化の良い候補ではないと思います。

これはアルゴリズムです:

const uchar* center = ...;

int t0, t1, val;
t0 = center[0]; t1 = center[1];
val = t0 < t1;
t0 = center[2]; t1 = center[3];
val |= (t0 < t1) << 1;
t0 = center[4]; t1 = center[5];
val |= (t0 < t1) << 2;
t0 = center[6]; t1 = center[7];
val |= (t0 < t1) << 3;
t0 = center[8]; t1 = center[9];
val |= (t0 < t1) << 4;
t0 = center[10]; t1 = center[11];
val |= (t0 < t1) << 5;
t0 = center[12]; t1 = center[13];
val |= (t0 < t1) << 6;
t0 = center[14]; t1 = center[15];
val |= (t0 < t1) << 7;

d[i] = (uchar)val;

これは私がARMアセンブリで考えたことです:

VLD2.8 {d0, d1} ["center" addr]

8 ビット char を想定すると、この最初の操作では、すべての t0 値と t1 値が 2 つのレジスタに交互にロードされます。

VCLT.U8 d2, d0, d1

すべての比較に対して「less then」の単一操作。注: VCLT は 2 番目のオペランドとして #0 定数を使用した場合にのみ可能であることを読んだので、これは >= で反転する必要があります。ARMのドキュメントを読むと、8ビット値ごとの結果は、true(11111111)の場合は「すべて1」、false(00000000)の場合は「すべて0」になると思います。

VSHR.U8 d4, d2, #7

この右シフトは、レジスタ 8 ビット「セル」の 8 つの値のうち 7 つを削除します (主に 7 つの値を削除するため)。次のステップはq2でマップされた最初のdレジスタになるため、d4を使用しました。

ここで問題が始まります: シフトと OR。

VSHLL.U8 q2[1], d4[1], 1
VSHLL.U8 q2[2], d4[2], 2
...
VSHLL.U8 q2[7], d4[7], 7

左シフトについては、この方法しか想像できません ([offsets] を使用できる場合)。ドキュメントによると、d4 の代わりに Q2 を指定する必要があります。

VORR(.U8) d4[0], d4[1], d4[0]
VORR(.U8) d4[0], d4[2], d4[0]
...
VORR(.U8) d4[0], d4[7], d4[0]

最後のステップで結果が得られるはずです。

VST1.8 d4[0], [d[i] addr]

結果の単純なストア。

これは ARM NEON への私の最初のアプローチであるため、おそらく多くの仮定が正しくない可能性があります。考えられるエラーを理解し、可能であればより良い解決策を提案してください。

編集: これは、提案された解決策の後の最終的な作業コードです:

__asm__ __volatile ("VLD2.8 {d0, d1}, [%[ordered_center]] \n\t"
"VCGT.U8 d2, d1, d0 \n\t"
"MOV r1, 0x01 \n\t"
"MOV r2, 0x0200 \n\t"
"ORR r2, r2, r1 \n\t"
"MOV r1, 0x10 \n\t"
"MOV r3, 0x2000 \n\t"
"ORR r3, r3, r1 \n\t"
"MOVT r2, 0x0804 \n\t"
"MOVT r3, 0x8040 \n\t"
"VMOV.32 d3[0], r2 \n\t"
"VMOV.32 d3[1], r3 \n\t"
"VAND d0, d2, d3 \n\t"
"VPADDL.U8 d0, d0 \n\t"
"VPADDL.U16 d0, d0 \n\t"
"VPADDL.U32 d0, d0 \n\t"
"VST1.8 d0[0], [%[desc]] \n\t"
:
: [ordered_center] "r" (ordered_center), [desc] "r" (&desc[i])
: "d0", "d1", "d2", "d3", "r1", "r2", "r3");
4

3 に答える 3