質問

私の画像処理プロジェクトは、Grayscale画像で動作します。 ARM Cortex-A8プロセッサプラットフォームがあります。ネオンを利用したいです。

グレースケールの画像(以下の例を考えてください)があり、アロゴリズムでは列のみを追加する必要があります。

どうすればロードできますか 4つの8ビットピクセル値 並行して、それはそうです uint8_t, 、 なので 4つのuint32_t 128ビットのネオンレジスタの1つに?これを行うためにどのような本質的に使用する必要がありますか?

つまり:

alt text

注意深く見ると、255 + 255を実行する瞬間は512で、8ビットレジスタに保持できないため、32ビットとしてロードする必要があります。

例えば

255 255 255 255 ......... (640 pixels)
255 255 255 255
255 255 255 255
255 255 255 255
.
.
.
.
.
(480 pixels) 
役に立ちましたか?

解決

SIMDがARMでどのように機能するかを理解するのに少し時間を費やすことをお勧めします。見る:

を見てみましょう:

  1. http://blogs.arm.com/software-enablement/161-coding-for-neon-part-1-load-and-stores/
  2. http://blogs.arm.com/software-enablement/196-coding-for-neon-part-2-dealing-with-leftovers/
  3. http://blogs.arm.com/software-enablement/241-coding-for-neon-part-3-matrix-multipation/
  4. http://blogs.arm.com/software-enablement/277-coding-for-neon-part-4-shifting-left-and-right/

あなたを始めるために。その後、Domenが推奨するインラインアセンブラーまたは対応するARM内因性を使用してSIMDコードを実装できます。

他のヒント

コンパイラと拡張機能の欠如に依存します。

すなわち。 GCCの場合、これは出発点かもしれません: http://gcc.gnu.org/onlinedocs/gcc/arm-neon-intrinsics.html

最大480の8ビット値を合計する必要がある場合は、技術的に17ビットの中間ストレージが必要になります。ただし、2つの段階、つまり上位240行で追加を実行すると、それぞれ16ビットでそれを行うことができます。次に、2つの半分の結果を追加して、最終的な答えを得ることができます。

実際には、Vaddwと呼ばれるアルゴリズムに適したネオン命令があります。 QWordベクトルにDWORDベクトルを追加し、後者には前者の2倍の幅の要素が含まれます。あなたの場合、vaddw.u8を使用して、8ピクセルを8ピクセルに16ビットの蓄積者に追加できます。次に、vaddw.u16を使用して、8つの16ビット蓄積者の2つのセットを8つの32ビットの蓄積者の1つに追加できます。両方の半分を取得するには、命令を2回使用する必要があることに注意してください。

必要に応じて、VMOVNまたはVQMOVNを使用して、値を16ビットまたは8ビットに戻すこともできます。

4 8ビット値を4 32ビットレジスタにロードできる命令はありません。

それらをロードしてから、VSHLを2回使用する必要があります。ネオンは32のレジスタを使用できないため、8ピクセルで作業する必要があります(4ではなく)

16ビットのレジスタのみを使用できます。それだけで十分なはずです...

単一車線ロード命令を使用して4バイトをロードします(vld1 <register>[<lane>], [<address])q-registerに、2つの動きの指示を使用します(vmovl)最初に16に、次に32ビットまで宣伝します。結果は(GNU構文内)のようなものでなければなりません

vld1 d0[0], [<address>] @Now d0 = (*<addr>, *<addr+1>, *<addr+2>, *<addr+3>, <junk>, ... <junk> )
vmovl.u8 q0, d0 @Now q1 = (d0, d1) = ((uint16_t)*<addr>, ... (uint16_t)*<addr+3>, <junk>, ... <junk>)
vmovl.u16 q0, d2 @Now d0 = ((uint32_t)*<addr>, ... (uint32_t)*<addr+3>), d1 = (<junk>, ... <junk>)

あなたがそれを保証できるなら <address> 4バイトがアラインされてから書き込みます [<address>: 32] 代わりに、ロード命令では、サイクルを1つまたは2つ節約します。ただし、アドレスが調整されていない場合は、障害が発生します。

ええと、私はあなたがアセンブリではなく内因性を使用したいことに気付いたので、ここに本質的なものと同じことがあります。

uint32x4_t v8; // Will actually hold 4 uint8_t
v8 = vld1_lane_u32(ptr, v8, 0);
const uint16x4_t v16 = vget_low_u16(vmovl_u8(vreinterpret_u8_u32(v8)));
const uint32x4_t v32 = vmovl_u16(v16);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top