1

関心領域 (トリミング) アルゴリズムを含むいくつかの画像処理アルゴリズムを含むライブラリがあります。GCC でコンパイルすると、自動ベクトライザーは多くのコードを高速化しますが、Crop アルゴリズムのパフォーマンスを低下させます。ベクトライザーによって無視される特定のループにフラグを立てる方法はありますか、またはパフォーマンスを向上させるためにコードを構造化するより良い方法はありますか?

for (RowIndex=0;RowIndex<Destination.GetRows();++RowIndex)
{
    rowOffsetS = ((OriginY + RowIndex) * SizeX) + OriginX;
    rowOffsetD = (RowIndex * Destination.GetColumns());
    for (ColumnIndex=0;ColumnIndex<Destination.GetColumns();++ColumnIndex)
    {
        BufferSPtr=BufferS + rowOffsetS + ColumnIndex;
        BufferDPtr=BufferD + rowOffsetD + ColumnIndex;
        *BufferDPtr=*BufferSPtr;
    }
}

SizeXソースの幅は どこですか OriginX関心領域の左側です 関心 OriginY領域の上部です

4

1 に答える 1

0

ループの最適化フラグの変更については何も見つかりませんでしたが、ドキュメントによると、関数で属性optimize(ここここを参照) を使用して、その関数の最適化設定を次のようにオーバーライドできます。

void foo() __attribute__((optimize("O2", "inline-functions")))

いくつかの機能で変更したい場合は、#pragma GCC optimize次のすべての機能に設定するために使用できます (こちらを参照)。

したがって、自動ベクトル化を省略して、別の最適化フラグのセットを使用してクロップを含む関数をコンパイルできるはずです。これには、その関数のコンパイル フラグをハードコーディングするという欠点がありますが、私が見つけた最高のものです。

パフォーマンスを向上させるための再構築に関しては、コメントで既に述べた 2 つの点が思い浮かびます (範囲が重複しないと仮定して)。

  • ポインターを宣言して、__restrictエイリアスを作成しないことをコンパイラーに伝えます (1 つのポインターが指す領域は、関数内の他の方法ではアクセスされません)。BufferDへの書き込みが の内容を変更するかどうかわからない場合、オプティマイザーはアクセスを簡単に並べ替えることができないため、ポインターのエイリアシングの可能性はオプティマイザーにとって大きな障害となりBufferSます。

  • 内側のループを copy の呼び出しに置き換える:

    std::copy(BufferS + rowOffsetS, BufferS + rowOffsetS + Destination.GetColumns(), BufferD + rowOffsetD);
    

    関数はcopyかなり最適化されている可能性があります (おそらく引数を に転送しますmemmove)。これにより、コードが高速になり、コードが短くなる可能性があります (常にプラスになります)。

于 2012-09-18T13:44:11.070 に答える