1

私はMATLABでmexコードを記述して操作を行っています(操作はc ++のライブラリを使用しているため)。mexコードには、異なる引数値を使用してループ内で繰り返し呼び出される関数があり、各関数呼び出しが独立しているセクションがあります(つまり、1つの呼び出しの計算は前の呼び出しに依存しません)。したがって、これを高速化するために、複数のスレッドを作成するマルチスレッドコードを作成しました。正確なスレッド数はループの反復回数に等しく、この例ではこの値は10です。各スレッドはループ内の関数を個別の値として計算します。引数、スレッドが戻って結合し、さらに計算が行われ、結果が返されます。理論的には、これらすべてが私に良いスピードアップを与えるはずですが、マルチスレッドコードは通常のシングルスレッドコードよりもはるかに遅いことがわかります!! 私は非常に強力な24コアのマシンにアクセスできるので、各スレッドが別々のコアでスケジュールされることを期待していたので、これは完全に困惑しています。これにつながるものについて何かアイデアはありますか?これにつながるコードの一般的な問題/エラーはありますか?

どんな助けでも大歓迎です。

編集:ここの人々によって提案されたソリューションで提起された多くの疑問に答えるために、私のコードに関するいくつかの情報を共有したいと思います:1.各関数呼び出しは数分かかるので、スレッドの同期と生成はここでオーバーヘッドになるべきではありません(この場合の緩和状況はありますか、それに関する情報は本当に役に立ちます!)

  1. 各スレッドは共通のデータ構造、配列、行列にアクセスしますが、これらの値はまったく上書きされません。変数へのすべての書き込みは、スレッドに対してローカルな変数、ポインター、配列などに対して行われます。だから、私はここで多くのキャッシュミスがあるべきではないと推測していますか?

  2. また、共通のメモリ位置にスレッドが書き込まないため、コードにミューテックスセクションはありません。すべての書き込みは、スレッドに対してローカルなメモリ位置に行われます。

私はまだ私のマルチスレッド実装が機能していない理由を理解しようとしています:(だから、どんなポインタ/情報も本当に役に立ちます!

ありがとう!!

4

3 に答える 3

1

私はあなたの問題がmex固有のものではないと思います-これはSMPのマルチスレッドコードをプログラミングする際の通常のパフォーマンスの問題のように聞こえます。

すでに述べた潜在的な問題に少し追加するには:

  • 誤ったキャッシュライン共有:スレッドは独立して機能していると思うかもしれませんが、実際には同じキャッシュライン内の異なるデータにアクセスします。簡単な例:

    /* global variable accessible by all threads */
    int thread_data[nthreads];
    
    /* inside thread function */
    thread_data[thrid] = some_value;
    
  • 非効率的なメモリ帯域幅の使用率。NUMAシステムでは、CPUが独自のデータバンクにアクセスできるようにする必要があります。データを正しく分散しないと、CPUは他のCPUにメモリを要求します。それはあなたがそこにいるとは思わないコミュニケーションを意味します。

  • スレッドアフィニティ。上記の点にやや関連しています。計算の全期間中、スレッドを独自のCPUにバインドする必要があります。そうしないと、OSによって移行されてオーバーヘッドが発生し、アクセスするメモリバンクからさらに離れて移動する可能性があります。

于 2012-09-28T13:32:34.860 に答える
1

あなたはあなたのコードが何をするかを説明しなかったので、これは単なる推測です。

マルチスレッドは奇跡の治療法ではありません。コードのシングルスレッドチャンクであったものをマルチスレッド化すると、元のコードよりも遅くなる可能性がある多くの方法があります。スレッドの生成、同期、結合、および破棄には、かなりのオーバーヘッドが伴います。

手元のタスクが10組の数字を追加することだったと仮定します。追加ごとにスレッドを生成し、計算が終了したときに結合して破棄することでこれをマルチスレッドにすると、マルチスレッドバージョンは元のバージョンよりもはるかに遅くなります。スレッディングは、非常に短時間の計算を目的としたものではありません。スポーン、参加、破壊のコストは、これらの単純なタスクを並行して実行することで得られるスピードアップを圧倒します。

物事を遅くする別の方法は、並列操作を防ぐバリアを確立することです。たとえば、複数のライターが同じオブジェクトに同時にアクセスするのを防ぐためのミューテックス。その保護されたコードは小さい必要があります。スレッドの本体全体をミューテックスを装って動作させると、スレッドのオーバーヘッドが大量に追加されたシングルスレッドアプリケーションに相当します。

並列実行を妨げるこれらの障壁は、それらを適切に配置しなかった場合でも存在する可能性があります。それらの障壁のいくつかはC標準ライブラリにあります。POSIXは、ほとんどのライブラリ関数がスレッドセーフであることを義務付けています。この標準では、スレッドセーフである必要のない関数のみがリストされています。これらの計算でライブラリ関数を使用する場合、コードは基本的にシングルスレッドであるため、シングルスレッドのままにしておく方がよい場合があります。

于 2012-09-28T13:00:42.630 に答える
1

あなたの質問がどれほど一般的であるかを考えると、一般的な答えは、おそらく2つの効果があるということです。

  • スレッドの開始と停止(およびスレッドの同期)には大きなオーバーヘッドがあり、計算のスケーリングはオーバーヘッドを克服するのに十分ではありません。関数呼び出しごとの合計時間は、この問題にいくらかの光を当てます。
  • スレッドは互いに競合し、全体的なパフォーマンスを低下させる可能性があります。一般的なメカニズムは「キャッシュスラッシング」です。複数のコアが同じメモリコントローラーとキャッシュ階層の一部を共有するため、1つのスレッドが必要な情報でキャッシュを埋めることができますが、そのデータの一部は別のスレッドのニーズによって削除され、メインメモリへのトリップが増えます。メインメモリへのアクセスは非常に高価であるため、最終的には速度が低下します。

さまざまな数のスレッドでジョブをテストします。たとえば、2つのスレッドを使用することは有利ですが、4つ以上を使用することは有利ではないことが判明する場合があります。より詳細な回答については、計算のタイプ、データセットのサイズなど、質問に詳細を追加してください。

于 2012-09-28T13:08:04.243 に答える