2016-10-10 15 views
0

画像をブロック単位で処理するときに最も効率的な方法は何か不思議です。ベクター画像ブロックの処理を効率的に処理しますか?

その瞬間、8x8ブロックから1行のピクセル(1行8ピクセル、各8ビット深度)を読み取るなど、ベクトル化技術を適用しました。しかし、現代のプロセッサが128/256ビットのベクトル演算をサポートしているので、イメージブロックから2行のピクセルをロードするとコードの速度が向上すると思います。

しかし、問題は、メモリ内の画像(たとえば16x16画像、4つの8x8ブロックを含む)が最初のピクセルから最後のピクセルに連続して格納されることです。 1つの8ピクセル行の読み込みは簡単ですが、2行を一緒に読み込むためにポインタを操作するかイメージデータを整列する必要がありますか?

私はこの数字は明らかに私の問題を説明することができると思う: pixels' address in a image

をので、私たちは一緒に8つのピクセル(行)をロードするとき、我々は単純に1つの命令で初期ポインタ位置から8バイトのデータをロードします。 2行目をロードするときは、ポインタに9を追加して2行目をロードするだけです。

最初のポインタの位置からこれら2つの行(16ピクセル)を一緒に読み込む方法はありますか?

ありがとうございます!

+1

*「load」*と言うとき、ファイルからの読み込みを意味しますか?または、RAMからCPUレジスタに入れますか? –

+0

私は、RAMからCPUレジスタにデータを書き込むことを意味します。 – drinking

答えて

1

各行を一列に整列させるには、各行の最後を埋めることができます。行間のストライドよりも短いイメージ幅をサポートするコードを記述すると、アルゴリズムがイメージのサブセットで動作するようになります。

また、SIMDがうまく動作するためには、実際にすべてを整列させる必要はありません。連続していれば十分です。ほとんどのSIMD命令セット(SSE、NEONなど)は、アライメントされていないロード命令を持っています。特定の実装に応じて、多くのペナルティはないかもしれません。


同じSIMDベクトルに2つの異なる行をロードしません。たとえば、AVX2 VPSADBWを使用して8x8 SAD(絶対差の合計)を実行するには、各32バイトのロードで4つの異なる8x8ブロックの1行からデータを取得します。しかし、これで大丈夫です。ただ8x8のSAD結果を並列に生成するために、それを使用して、1回の8x8 SADを行うために多くの時間を浪費するのではなく、

たとえば、Intel's MPSADBW tutorialは、CおよびIntelのSSE組み込み関数を使用して、4x4,8x8,16x16ブロックの網羅的な動き検索を実装する方法を示しています。明らかに実際のMPSADBW命令はPSADBWよりも遅く、x264で使用されているような連続的な排除網羅的な検索でより高速になるため、実際に使用する価値はありません(でSSE4 0.1は、x264のに役立つだろう)

いくつかのSIMDプログラミングのブログ記事をダークシカリのブログのアーカイブから:。

+0

しかし、各行の最後にゼロを埋めても、ブロック内に2つの行をロードする方法は分かりません。私はアンロードされたロード命令が1つの命令でトウの行をロードするのを助けないと思いますか? – drinking

+0

コンパイラがそれをベクトル化するコードを設定しますか?あるいは、あなた自身が頑張っていますか?コンパイラが同じ結果を得ても、後で新しいAVXや他のアーキテクチャーに行くときには、もう一度手を加える必要があります。 #pragmaのすべてのものは、ポインタと連続したアクセスをどのように扱うかによって、コンパイラにそれをソートするのに十分なことがよくあります。 – Holmz

+0

@飲み物:複数のブロックから同じ行を読み込み、複数のブロックを並列に処理するので、その必要はありません。私の更新された答えを見てください。 –