2015-10-04 5 views
5

イメージ内に単一のRGBピクセルを格納する構造体を作成しています。3つのカラーコンポーネントのみを持つ浮動小数点ピクセルでSSEを使用する

struct Pixel 
{ 
    // color values range from 0.0 to 1.0 
    float r, g, b; 
}__attribute__((aligned(16)); 

私はなど、乗算、私は一度にすべての3つのカラーチャンネルの操作を行うことができるこの方法を追加するようなものを行うために128ビットSSE命令を使用します。だから、私のSSE登録簿に最初に詰め込まれたフロートは、赤、緑、そして青ですが、私は4番目の登録簿に何が入るか分かりません。余分な32ビットのパディングにどのビットが入っているかは本当に気にしません。 SSEレジスタにピクセルをロードすると、ゼロまたはジャンク値のいずれかが含まれていると思います。これは問題なのでしょうか?私が実際には必要ないのに4番目のアルファチャンネルを追加すべきでしょうか?私がこれが問題であると思う唯一の方法は、ピクセルで割って4番目のスポットにゼロの値があった場合、またはネガの根をとっている場合などです。

+1

厳密には準拠していないため、「valgrind」や「アドレスサニタイザー」などのツールは不平を言う可能性があります。私はこれが実際にはうまくいかない理由は何も見ません。 – EOF

+2

@EOF:FPデータには技術的な理由があります:FP例外、および初期化されていないデータがNaN、無限大、または非正規の浮動小数点を表す場合、CPUによっては大きなパフォーマンス上の不利益があります。 –

+0

このような大きな精度をカラーチャンネルに使用したい理由はありますか?ストレージについては、代わりにハーフフロートを使用することがありますが、処理についてはわかりません –

答えて

9

整数オペレイテンシは決してデータに依存しないため、初期化されていない値では全く問題がありません。浮動小数点は異なります。一部のFPUは、非正規化、NaN、および無限大(ベクトル要素のいずれか1つ)で減速します。

インテルNehalem以前は、正規表現入出力を使用して数学演算を実行しているとき、およびFPアンダーフロー/オーバーフロー時に多くの速度が低下します。 Sandybridgeには、すべての入力に対して(Agner Fog's instruction tablesによる)高速加算/減算付きの素敵なFPUがありますが、multiply can still slow downです。

追加/サブ/乗算は0で問題ありませんが、NaNなどを表す初期化されていない迷惑メールの問題が発生する可能性があります。

0で除算しない除算には注意してください。これにより、HWの設定に応じてFPU例外が発生する可能性があります。

はい、使用されていない要素をゼロに保つことは、おそらく良い考えです。最初に物事をどのように生成するかによって、これはかなり安いかもしれません。 (例えば、movd/pinsrd/pinsrd(またはinsertps)を使用して、3つの32ビット要素をベクトルに入れて、最初のmovdで96bをゼロにします)。

青いチャネルの2番目のコピーを4番目の素子。 (またはそこにシャッフルするのが最も便利なもの)movsldup(SSE3)/ movlpsというベクトルをロードできます。 movsldupの後、あなたの登録簿は{ b b r r }を保持するでしょう。 movlpsは下位64ビットを再ロードするので、{ b b g r }になります。 (これは、movsd、BTWと同等です)。シャッフルポートが負荷ポートよりビジーでない場合は、1つの16Bロードを実行してshufpsします。 (Intel CPU上のmovsldupは、重複が組み込まれていても、ロードポートで実行される単一のuopです)。

もう1つの方法は、16Bの負荷で1つのコンポーネント次のピクセルのあなたがやっていることに応じて、次のピクセルの1つの要素を壊すようなオーバーラップするストアは、問題ないかもしれません。電流を保存する前に次のピクセルをロードすると、いくつかのオペレーションでそれを回避することができます。キャッシュや帯域幅制限が非常に簡単なので、時折キャッシュライン分割ロード/ストアのわずかなコストで1/4スペースを節約する価値があります。

+3

Sandybridgeは、SSE/AVXの異常なストールを完全に排除しませんでした(ブロードウェルのいくつかのケースでは依然として存在しています)が、最も一般的なケースではそれらを排除しました。ゼロで割ることは、SSE/AVXでは安全です。フラグを設定しますが、デフォルトの浮動小数点環境ではトラップしません。次のピクセルからのパッキングと読み込みのリスクは、4の倍数ではないピクセル数がある場合、バッファの最後の最後の読み込みでは、制御していないデータが読み取られます(マップされていない可能性もあります)。 (無関係なメモをコメントにまとめることについての謝罪)。 –

+0

@stephen:異常な減速とdivによる情報をありがとう。私は言及していませんでしたが、write-past-the-end問題を処理する最善の方法は、バッファにパディングを割り当てることです。または、ループ1の反復を早く終了し、最後のトリプレットを 'movlps/extractps'で処理します。あるいは、 'palignr/movups'を使って16B書き込みを行い、前のピクセルの上位要素を書き換えます。 (あなたがループから脱出するときにはまだレジスタに入っているので)私は通常、1つのコメントで3つのコメントのうち3つを1行に残すのではなく、複数のトピックを扱います。 :) –

+2

Agner Fogはもともと、Sandy Bridgeで高速だった加減算の非正規化をテストしました。誰かが[ここに気付く]までそれはなかった(http://stackoverflow.com/questions/9314534/why-does-changing-0-1f-to-0-slow-down-performance-by-10x/9314926#コメント11910304_9314926)は、Agnerのブログに話を進め、再テストを行い、Sandy Bridgeの非正規化に対して乗法がまだ脆弱であることを発見しました。 – Mysticial

関連する問題