4
SIMDプログラミングコードベースのメンテナンスコスト
質問: ソフトウェア業界のコンセンサスは、クリーンでシンプルなコードが、コードベースとそれを所有する組織の長期的な実行可能性の基本であるということです。これらのプロパティにより、メンテナンスコストが削減され、コードベースが継続される可能性が高まります。 ただし、SIMDコードは一般的なアプリケーションコードとは異なります。SIMDコードに特に適用されるクリーンでシンプルなコードに関して、同様のコンセンサスがあるかどうかを知りたいと思います。 私の質問の背景。 さまざまな画像処理および分析タスクのために、たくさんのSIMD(単一命令、複数データ)コードを作成します。最近、これらの関数のいくつかを、あるアーキテクチャ(SSE2)から別のアーキテクチャ(ARM NEON)に移植しなければなりませんでした。 このコードはシュリンクラップされたソフトウェア用に記述されているため、MATLABなどの無制限の再配布権がなければ、独自の言語に依存することはできません。 典型的なコード構造の例: 使用のOpenCVのマトリックスタイプ(Mat)すべてのメモリのため、緩衝液および寿命管理。 入力引数のサイズ(次元)を確認した後、ピクセルの各行の開始アドレスへのポインターが取得されます。 ピクセルカウント、および各入力マトリックスからのピクセルの各行の開始アドレスは、いくつかの低レベルC ++関数に渡されます。 これらの低レベルC ++関数は、SIMD組み込み関数(Intel ArchitectureおよびARM NEON用)を使用して、生のポインターアドレスからの読み込みと保存を行います。 これらの低レベルC ++関数の特徴: 排他的に1次元(メモリ内で連続) メモリ割り当てを処理しません。(一時を含むすべての割り当ては、OpenCV機能を使用する外部コードによって処理されます。) シンボルの名前の長さの範囲(組み込み関数、変数名など)は約10〜20文字で、これは非常に過剰です。(テクノバブルのように読みます。) コンパイラは「単一割り当て」コーディングスタイルで記述されていないコードを正しく解析するのに非常にバグがあるため、SIMD変数の再利用は推奨されません。(私はいくつかのコンパイラのバグレポートを提出しました。) SIMDプログラミングのどの側面が議論を一般的な場合と異なるものにしますか?または、SIMDが異なるのはなぜですか? 初期開発コストの観点から 優れたパフォーマンスを備えたC ++ SIMDコードの初期開発コストは、カジュアルに記述された C ++コードと比較して、約10倍から100倍(マージンは大きい)であることはよく知られています。 パフォーマンスと読み取り可能/クリーナーコードの選択の回答で述べたように?、ほとんどのコード(カジュアルに記述されたコードとSIMDコードを含む)は、最初はクリーンでも高速でもありません。 (スカラーコードとSIMDコードの両方での)コードパフォーマンスの進化的な改善は推奨されません(ソフトウェアの一種と見なされるため)。コストと利点は追跡されません。 傾向の観点から (例えば、パレート原理、別名80-20ルール) 画像処理がソフトウェアシステムの20%(コードサイズと機能の両方)のみで構成されている場合でも、画像処理は(CPU時間の割合として見た場合)比較的遅く、80%以上の時間がかかります。 これは、データサイズの影響によるものです。典型的な画像サイズはメガバイト単位で測定されますが、非画像データの典型的なサイズはキロバイト単位で測定されます。 画像処理コード内で、SIMDプログラマーは、C ++コード内のループ構造を識別することにより、ホットスポットを含む20%コードを自動的に認識するように訓練されます。したがって、SIMDプログラマーの観点からは、「重要なコード」の100%がパフォーマンスのボトルネックです。 多くの場合、画像処理システムには複数のホットスポットが存在し、同等の割合の時間を消費します。たとえば、5つのホットスポットがそれぞれ合計時間(20%、18%、16%、14%、12%)を占める場合があります。高いパフォーマンスを実現するには、すべてのホットスポットをSIMDで書き換える必要があります。 これは、バルーンをポップするルールとして要約されています。バルーンを2回ポップすることはできません。 バルーンがいくつかあると仮定します。たとえば、そのうち5つです。それらを間引く唯一の方法は、それらを1つずつポップすることです。 最初のバルーンがポップされると、残りの4つのバルーンの合計実行時間の割合が高くなります。 さらに利益を上げるには、別のバルーンをポップする必要があります。(これは、最適化の80-20ルールに反します:ぶら下がりが最も少ない果物の20%が選ばれた後、良好な経済的結果を達成できます。) 読みやすさとメンテナンスの面で SIMDコードは、明らかに読みにくいです。 これは、すべてのソフトウェアエンジニアリングのベストプラクティス(ネーミング、カプセル化、const-correctness(および副作用の明確化)、関数の分解など)に従っても当てはまります。 これは、経験のあるSIMDプログラマーにも当てはまります。 最適なSIMDコードは、同等のC ++プロトタイプコードと比較して、非常にゆがんでいます(注意を参照)。 SIMDコードをゆがめる方法は数多くありますが、10回の試行のうち1回だけで許容可能な高速の結果が得られます。 (つまり、高い開発コストを正当化するために、4倍から10倍のパフォーマンスゲインを調整します。実際には、さらに高いゲインが観察されています。) …