2012-02-15 20 views
5

私のCPUはコア2個とスレッド4個のCore i3 330Mです。私の端末にcat /proc/cpuinfoというコマンドを実行すると、私は4 CPUSを持っているようです。 OpenMP関数を使用すると、get_omp_num_procs()も得られます。OpenMPとコア/スレッド

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

問題は次のとおりです。このような単純なケースでは、予想されるスピードアップを推測できますか?たとえば、並列化されたfor-loopsなしで2つのベクトルを追加すると、(shell 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がどのように仕事をするのか、誰かがもっと教えてくれることを願っています。私は並列計算の初心者だと言わなければならない。

ありがとうございます!

答えて

3

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

この特定の例では、非常に少ない計算量と多くのメモリアクセスがあります。したがって、パフォーマンスは大きく依存します:

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

大きなベクトルサイズの場合、パフォーマンスはメモリ帯域幅によって制限される可能性があります。この場合、並列性はあまり役に立たないでしょう。より小さなサイズの場合、スレッディングのオーバーヘッドが支配的になります。 "期待される"スピードアップを得ているなら、おそらく結果が最適となる場所の間にいるでしょう。

一般的に、マルチスレッドアプリケーションでの「推測」パフォーマンスは、事前のテスト知識や、実行されているシステムとシステムの両方に関する詳細な知識がないと失われます。 3 @コアi7の920でHow to get 100% CPU usage from a C program

:ちょうどここに私の答えから取られた簡単な例として

。5 GHz帯(4個のコア、8つのスレッド):

私は4スレッドで実行すると、結果は次のとおりです。私は4スレッドと明示的に実行した場合(タスクマネージャを使用して)

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

4つの異なる物理コアにスレッドをピン結果は:

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

これは、非常に簡単で難解な並列アプリケーションでさえ予測できないことを示しています。大量のメモリ使用と同期を必要とするアプリケーションは、もっと醜いものになります...

1

神秘的な答えに追加します。あなたの問題は純粋にメモリ帯域幅に限定されていますSTREAM benchmarkをご覧ください。あなたのコンピュータ上で、シングルスレッドやマルチスレッドの場合に実行し、トライアドの結果を見てください。これはあなたのケースです(あなたの出力ベクトルは入力ベクトルの1つと同じ時刻になるのでほぼ同じです)。どのくらいのデータを移動するかを計算します。期待するパフォーマンスを正確に把握できます。

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

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