7

私のCPUは2コア4スレッドのCore i3 330Mです。端末でコマンド cat を実行すると、/proc/cpuinfo4 つの CPU があるように見えます。OpenMP 関数を使用すると、get_omp_num_procs()4 も取得されます。

これで、標準の C++ ベクトル クラスができました。これは、式テンプレートを使用しない固定サイズの double 配列クラスを意味します。クラスのすべてのメソッドを慎重に並列化したところ、「期待される」スピードアップが得られました。

問題は、このような単純なケースで期待されるスピードアップを推測できるかどうかです。たとえば、並列化された for ループを使用せずに 2 つのベクトルを追加すると、(シェルの time コマンドを使用して) ある程度の時間が得られます。OpenMP を使用する場合、コア/スレッドの数に応じて、時間を 2 または 4 で割った値を取得する必要がありますか? データに相互依存性がなく、すべてが線形 (ベクトル加算) である、この特定の単純な問題のみを求めていることを強調します。

ここにいくつかのコードがあります:

Vector Vector::operator+(const Vector& rhs) const
{
    assert(m_size == rhs.m_size);
    Vector result(m_size);
    #pragma omp parallel for schedule(static)
    for (unsigned int i = 0; i < m_size; i++) 
            result.m_data[i] = m_data[i]+rhs.m_data[i];

    return result;
}

私はすでにこの投稿を読みました: OpenMP thread mapping to physical cores .

この単純なケースで OpenMP がどのように機能するかについて、誰かが詳しく教えてくれることを願っています。私は並列計算の初心者です。

ありがとう!

4

2 に答える 2

4

編集:いくつかのコードが追加されました。

その特定の例では、計算はほとんど行われず、大量のメモリ アクセスが行われます。したがって、パフォーマンスは次の要素に大きく依存します。

  • ベクトルのサイズ。
  • どのようにタイミングをとっていますか。(タイミング目的で外側のループはありますか)
  • データが既にキャッシュにあるかどうか。

大きなベクトル サイズの場合、メモリ帯域幅によってパフォーマンスが制限される可能性があります。その場合、並列処理はあまり役に立ちません。サイズが小さい場合、スレッド化のオーバーヘッドが支配的になります。「期待される」スピードアップが得られている場合は、最適な結果が得られる中間の位置にいる可能性があります。

一般に、特にマルチスレッド アプリケーションでの「推測」パフォーマンスは、テストに関する事前の知識、またはプログラムとそれが実行されているシステムの両方に関する詳細な知識がない限り、失われた原因であるため、具体的な数値を示すことは拒否します。

ここでの私の答えから取った簡単な例として: C プログラムから 100% の CPU 使用率を取得する方法

Core i7 920 @ 3.5 GHz (4 コア、8 スレッド):

4 つのスレッドで実行すると、結果は次のようになります。

This machine calculated all 78498 prime numbers under 1000000 in 39.3498 seconds

4 つのスレッドで実行し、明示的に (タスク マネージャーを使用して)スレッドを 4 つの異なる物理コアに固定すると、結果は次のようになります。

This machine calculated all 78498 prime numbers under 1000000 in 30.4429 seconds

したがって、これは、非常に単純で恥ずかしいほどの並列アプリケーションであっても、それがいかに予測不可能であるかを示しています。大量のメモリ使用と同期を伴うアプリケーションは、はるかに醜くなります...

于 2012-02-15T12:21:54.003 に答える
1

Mysticals の回答に追加します。あなたの問題は、純粋にメモリ帯域幅が制限されていることです。STREAM ベンチマークを見てください。シングルスレッドとマルチスレッドの場合でコンピュータ上で実行し、Triad の結果を見てください - これはあなたの場合です (ほとんどの場合、出力ベクトルは同時に入力ベクトルの 1 つなので)。移動するデータの量を計算すると、期待されるパフォーマンスが正確にわかります。

マルチスレッドはこの問題に対応していますか? はい。単一の CPU コアがシステムのメモリ帯域幅全体を飽和させることはまれです。最新のコンピューターは、使用可能なメモリ帯域幅と使用可能なコア数のバランスをとっています。私の経験から、単純な memcopy 操作でメモリ帯域幅を飽和させるには、約半分のコアが必要になります。途中で計算するともう少しかかるかもしれません。

NUMA システムでは、スレッドを CPU コアにバインドし、ローカル メモリ割り当てを使用して最適な結果を得る必要があることに注意してください。これは、そのようなシステムでは、すべての CPU が独自のローカル メモリを持ち、アクセスが最も速いためです。通常の SMP のようにシステム メモリ全体にアクセスできますが、これには通信コストが発生します。CPU は明示的にデータを交換する必要があります。スレッドを CPU にバインドし、ローカル割り当てを使用することは非常に重要です。これを怠ると、スケーラビリティが失われます。Linux でこれを行う場合は、libnuma を確認してください。

于 2012-09-21T12:31:59.657 に答える