マルチコア/マルチ CPU マシンにループ内の関数呼び出しを並列処理するように指示するにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/56769

  •  09-06-2019
  •  | 
  •  

質問

現在、データベースから大量のデータをロードし、状況に応じてさまざまな計算によってデータをより小さなセットに削減する 1 つのモジュールを持つアプリケーションを設計しています。

より集中的な操作の多くは決定論的に動作するため、並列処理に適しています。

データベースから到着する多数のデータチャンクを反復処理するループがあり、各データチャンクに対して副作用なしで決定論的な関数を呼び出す場合、プログラムが関数が返されるのを待たずに設定を行うようにするにはどうすればよいですか?次の呼び出しは並行して処理できるようになりますか?今のところは、原理を実証する素朴なアプローチで十分でしょう。

Google の MapReduce 論文を読みました。全体的な原則はさまざまな場所で使用できますが、今のところ、大規模なクラスターをターゲットにするつもりはありません。むしろ、バージョン 1.0 では単一のマルチコアまたはマルチ CPU マシンになる予定です。 。したがって、現時点では、このライブラリを実際に使用できるかどうか、または自分で機能を簡素化した基本バージョンをロールアウトする必要があるかどうかはわかりません。

私は設計プロセスの初期段階にあり、今のところ言語として C 系のもの (速度が重要な部分) と Python (生産性が重要な部分) をターゲットにしています。やむを得ない理由があれば乗り換えるかもしれませんが、今のところは自分の選択に満足しています。

現在のチャンクを処理するよりもデータベースから次のチャンクを取得する方が時間がかかり、プロセス全体が I/O バウンドになる可能性があるという事実を承知していることに注意してください。ただし、現時点ではそうではないと仮定し、実際には、この時点で I/O バウンドにならないように DB クラスター、メモリ キャッシュ、またはその他のものを使用します。

役に立ちましたか?

解決

ここで何かが欠けているかもしれませんが、これは pthread を使用することで非常に簡単に思えます。

N 個のスレッドを含む小さなスレッドプールをセットアップし、1 つのスレッドでそれらすべてを制御します。

マスター スレッドは単にループ内に存在し、次のようなことを実行します。

  1. DBからデータチャンクを取得
  2. 次の空きスレッドを探す 空きスレッドがない場合は待機します
  3. チャンクをワーカースレッドに引き渡す
  4. 戻って DB から次のチャンクを取得します

その間、ワーカースレッドは座って次のことを実行します。

  1. 自分を自由としてマークします
  2. マストスレッドがデータの塊を提供するのを待ちます
  3. データの塊を処理する
  4. 自分を再びフリーとしてマークします

これを実装する方法は、2 つのミューテックス制御配列と同じくらい簡単です。1 つは作業中のスレッド (スレッドプール) を持ち、もう 1 つは対応する各スレッドがフリーかビジーかを示します。

Nを好みに合わせて微調整してください...

他のヒント

そうですね、.net がオプションである場合、彼らは多大な努力を払ってきました。 並列コンピューティング.

まだ Python を使用する予定がある場合は、以下を参照してください。 処理. 。これは (Python GIL により) 並列計算にスレッドではなくプロセスを使用し、「作業項目」を複数のプロセスに分散するためのクラスを提供します。プール クラスを使用すると、次のようなコードを作成できます。

import processing

def worker(i):
    return i*i
num_workers = 2
pool = processing.Pool(num_workers)
result = pool.imap(worker, range(100000))

これは itertools.imap の並列バージョンであり、呼び出しをプロセスに分散します。プールの apply_async メソッドを使用して、遅延結果オブジェクトをリストに保存することもできます。

results = []
for i in range(10000):
    results.append(pool.apply_async(worker, i))

詳細については、次を参照してください。 Pool クラスのドキュメント.

注意点:

  • fork()を使った処理なのでWin32では注意が必要
  • プロセス間で転送されるオブジェクトはピクルス可能である必要がある
  • ワーカーが比較的高速な場合は、チャンクサイズを調整できます。1 つのバッチでワーカー プロセスに送信される作業項目の数
  • process.Pool はバックグラウンド スレッドを使用します

Google のアルゴリズムを実装できます。 MapReduce 物理的に別々のマシンを持たずに済みます。これらの「マシン」のそれぞれが「スレッド」であると考えてください。スレッドは、マルチコアマシンに自動的に配布されます。

それをサポートするコンパイラを使用している場合は、以下を参照することをお勧めします。 http://www.openmp.org 特定のループが並列化されるようにコードを注釈する方法のために。

他にもたくさんの機能があり、非常に役立つかもしれません。

たとえば、彼らの Web ページでは、gcc4.2 が openmp をサポートすると報告しています。

Javaでも同じスレッドプールが使用されます。ただし、スレッドプール内のスレッドはシリアル化可能で、他のコンピューターに送信され、デシリアル化されて実行されます。

単一サーバー上でマルチスレッド/マルチコアで使用するための MapReduce ライブラリを開発しました。すべてはライブラリによって処理され、ユーザーは Map と Reduce を実装するだけで済みます。これは Boost ライブラリとして位置付けられていますが、まだ正式なライブラリとしては受け入れられていません。チェックアウト http://www.craighenderson.co.uk/mapreduce

コードを調べることに興味があるかもしれません libdispatch, 、これは Apple の Grand Central Dispatch のオープンソース実装です。

Intel の TBB または boost::mpi にも興味があるかもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top