15

私のコードベースには、大きなデータセットに対して同じ操作が非常に多く繰り返される場所がいくつかあります。場合によっては、これらの処理にかなりの時間がかかります。

SSE を使用してこれらのループを実装すると、特に同じデータ セットに対して多くの操作が実行される場合に、パフォーマンスが大幅に向上すると考えています。それ。しかし、私はこれについて行くことについて確信が持てません。

  • SSE命令を利用するためにコードを書くコンパイラとOSに依存しない方法はありますか? SSE 操作を含む VC++ 組み込み関数が気に入っていますが、クロス コンパイラ ソリューションは見つかりませんでした。

  • SSE サポートがない、または制限されている一部の CPU (Intel Celeron など) をサポートする必要があります。プロセスの開始時に実行されている CPU に基づいて、基本コードまたは SSE 最適化コードのいずれかにリンクするある種の「実行時リンカー」を使用するなど、プログラムの異なるバージョンを作成する必要を回避する方法はありますか?

  • 他の CPU 拡張機能についてはどうでしょうか。さまざまな Intel および AMD CPU の命令セットを見ると、それらのいくつかが示されていますか?

4

5 に答える 5

7

2番目のポイントについては、違いをさまざまな機能に分離できる限り、いくつかの解決策があります。

  • 単純な古い C 関数ポインター
  • 動的リンク (通常は C 関数ポインターに依存します)
  • C++ を使用している場合、さまざまなアーキテクチャのサポートを表すさまざまなクラスを用意し、仮想関数を使用すると、これに非常に役立ちます。

間接的な関数呼び出しに依存しているため、さまざまな操作を抽象化する関数は、通常、やや高いレベルの機能を表す必要があることに注意してください。そうしないと、呼び出しのオーバーヘッドで最適化された命令から得られる利益が失われる可能性がありますt 個々の SSE 操作を抽象化する - 実行中の作業を抽象化します)。

関数ポインタを使用した例を次に示します。

typedef int (*scale_func_ptr)( int scalar, int* pData, int count);


int non_sse_scale( int scalar, int* pData, int count)
{
    // do whatever work needs done, without SSE so it'll work on older CPUs

    return 0;
}

int sse_scale( int scalar, in pData, int count)
{
    // equivalent code, but uses SSE

    return 0;
}


// at initialization

scale_func_ptr scale_func = non_sse_scale;

if (useSSE) {
    scale_func = sse_scale;
}


// now, when you want to do the work:

scale_func( 12, theData_ptr, 512);  // this will call the routine that tailored to SSE 
                                    // if the CPU supports it, otherwise calls the non-SSE
                                    // version of the function
于 2009-12-12T22:08:20.093 に答える
6

この件に関する良い読み物:命令セット戦争を止めてください

簡単な概要: 申し訳ありませんが、簡単で最も互換性のある (Intel と AMD の) 方法で問題を解決することはできません。

于 2009-12-12T19:39:24.200 に答える
4

SSE 組み込み関数は、Visual C++、GCC、Intel コンパイラで動作します。最近では使用に問題はありません。

SSE を使用しないバージョンのコードを常に保持し、SSE 実装に対して常にチェックする必要があることに注意してください。

これはデバッグに役立つだけでなく、必要な SSE バージョンをサポートしていない CPU やアーキテクチャをサポートしたい場合にも役立ちます。

于 2009-12-12T19:59:48.997 に答える
3

あなたのコメントに答えて:

事実上、サポートされていない命令を含むコードを実際に実行しようとしない限り、問題はなく、「if(see2Supported){...}else{...}」タイプのスイッチで問題を解決できますか?

依存します。SSE 命令が実行されない限り、バイナリに存在しても問題ありません。CPUはそれで問題ありません。

ただし、コンパイラで SSE サポートを有効にすると、多くの「通常の」命令が同等の SSE (スカラー浮動小数点演算など) に置き換えられる可能性が高いため、通常の非 SSE コードのチャンクでさえ壊れます。それをサポートしていない CPU で起動します。

したがって、SSE を有効にして、1 つまたは 2 つのファイルを別々にコンパイルし、それらにすべての SSE ルーチンを含める必要があります。次に、それを SSE サポートなしでコンパイルされたアプリの残りの部分とリンクします。

于 2009-12-13T11:06:38.140 に答える
1

別の SSE 実装をスカラー コードに手作業でコーディングするのではなく、OpenCLを確認することを強くお勧めします。これは、計算量の多いアプリケーション向けの、ベンダーに依存しないポータブルなクロスプラットフォーム システムです (そして、バズワードに高度に準拠しています!)。ベクトル化された操作用に設計された C99 のサブセットでアルゴリズムを記述できます。これは、SSE を手作業でコーディングするよりもはるかに簡単です。そして何よりも、OpenCL は実行時に最適な実装を生成し、GPUまたはCPU で実行します。したがって、基本的には、SSE コードが作成されます。

私のコード ベースには、大規模なデータ セットに対して同じ操作が非常に多く繰り返される場所がいくつかあります。場合によっては、これらの処理にかなりの時間がかかります。

あなたのアプリケーションは、まさに OpenCL が対処するように設計された種類の問題のように思えます。SSE で代替関数を作成すると、確かに実行速度が向上しますが、作成とデバッグには多大な労力がかかります。

SSE命令を利用するためにコードを書くコンパイラとOSに依存しない方法はありますか? SSE 操作を含む VC++ 組み込み関数が気に入っていますが、クロス コンパイラ ソリューションは見つかりませんでした。

はい。SSE 組み込み関数は基本的に Intel によって標準化されているため、Windows、Linux、および Mac (特に Visual C++ と GNU g++) の間で同じ関数が同じように機能します。

SSE サポートがない、または制限されている一部の CPU (Intel Celeron など) をサポートする必要があります。プロセスの開始時に実行されている CPU に基づいて、基本コードまたは SSE 最適化コードのいずれかにリンクするある種の「実行時リンカー」を使用するなど、プログラムの異なるバージョンを作成する必要を回避する方法はありますか?

それを行うこともできますが (例: を使用dlopen())、これは非常に複雑なソリューションです。(C で) 関数インターフェイスを定義し、関数ポインターを介して最適化された関数の適切なバージョンを呼び出すか、C++ で検出された CPU に応じて異なる実装クラスを使用する方がはるかに簡単です。

OpenCL では、特定のアーキテクチャの実行時にコードが生成されるため、これを行う必要はありません。

他の CPU 拡張機能についてはどうですか。さまざまな Intel および AMD CPU の命令セットを見ると、それらのいくつかが示されていますか?

SSE 命令セットには、さまざまな種類があります。特定の命令が存在しない場合、SSE の異なるサブセットで同じアルゴリズムをコーディングすることは非常に困難です。(少なくとも最初は) SSE2 などのサポートされている最小レベルを選択し、古いマシンではスカラー実装にフォールバックすることをお勧めします。

これは、ユニット/回帰テストの理想的な状況でもあり、さまざまな実装で同じ結果が得られるようにするために非常に重要です。入力データと既知の適切な出力データのテスト スイートを用意し、両方のバージョンの処理関数で同じデータを実行します。合格するには、精度テストが必要になる場合があります (つまり、結果と正解の差のイプシロンは、1e6たとえば以下のようになります)。これはデバッグに非常に役立ちます。テスト フレームワークに高解像度のタイミングを組み込むと、同時にパフォーマンスの向上を比較できます。

于 2009-12-14T10:53:32.457 に答える