並列評価
リモートカーネルにコマンドを送る
リモートカーネルへの接続は,LaunchKernelsで開くことからわかるように,カーネルオブジェクトとして表される.詳細は「起動と接続」を参照されたい.このセクションのコマンドは引数に並列カーネルを取り,それを計算の実行に使用する.
低レベル並列評価
ParallelEvaluate[cmd,kernel] | cmd を評価のために並列カーネル kernel に送り,結果を待ってそれを返す |
ParallelEvaluate[cmd,{kernels}] | cmd を評価のために指定の並列カーネルに送り,結果を待ってそれらを返す |
ParallelEvaluate[cmd] | cmd を評価のために全並列カーネルに送り,結果のリストを返す.ParallelEvaluate[cmd,Kernels[]]と同等である |
リモートカーネルへのコマンドの送信と,リモートカーネルからのコマンドの受信
ParallelEvaluateは属性HoldFirstを持つ.
ParallelSubmitまたはWaitAllを含む並行計算が実行中のときはParallelEvaluateは使えない.詳しくは「並行性:並列プロセスを管理する」を参照されたい.
変数の値
ローカルのマスターカーネルで定義された変数の値は,通常リモートカーネルでは利用できない.評価に送信したコマンドが変数を参照している場合は,希望通りには動作しない場合がある.
ただし,便宜上,デフォルトのコンテキストで作成された対話型セッションで定義した変数の値は,自動的に配布される.
変数の値と定義をリモートカーネルに引き継ぎたい場合は,DistributeDefinitionsまたは共有変数を使う.
Table,Do等の反復子は反復子変数に関しては同じように動作する.したがって,以下のような文は希望通りには動作しない.
パターン変数,定数,純関数変数はリモートカーネル上で希望通りに動作する.次の3つの例はそれぞれ希望通りの結果を出す.
式の並列評価
ParallelCombine[f,h[e1,e2,…,en],comb] | f[h[e1,e2,…,en]]を分割した f[h[ei,ei+1,…,ei+k]]を全カーネルに配布し,結果を comb[]で結合することで並列に評価する |
ParallelCombine[f,h[e1,e2,…,en]] | h が属性Flatを持つ場合はデフォルトの結合子 comb は h,それ以外の場合はJoinである |
ParallelCombine[f,h[e1,e2,…,en],comb]は h[e1,e2,…,en]を部分 h[ei,ei+1,…,ei+k]に分割し,f[h[ei,ei+1,…,ei+k]]を並列に評価し,comb[r1,r2,…,rm]を使って結果 ri を結合する.ParallelCombineは属性HoldFirstを持っているので,h[e1,e2,…,en]は並列化の前にマスターカーネルで評価されない.
ParallelCombine
ParallelCombineは引数のデフォルト値がリストや結合関数等のコンテナの要素の評価に適しており,一般的で強力なコマンドである.
リスト様のコンテナを評価する
関数 f をリストに適用した結果が再びリストなら,ParallelCombine[f,h[e1,e2,…,en],comb]は f を入力リストの各部分に適用し,部分的な結果を結合する.
結果はPrime[{1,2,3,4,5,6,7,8,9}]の結果と同じであるが,計算は並列に行われる.
関数がIdentityなら,ParallelCombineは単に要素 ei を並列に評価する.
関数 f をリストに適用した結果がリストでないなら,カスタム結合子を選ばなければならない.
関数Function[li,Count[li,_?OddQ]]はりスト中の奇数の数を数える.奇数の総数を求めるためには,部分結果を加え合せる.
結合演算を評価する
h[e1,e2,…,en]の演算 h が結合演算(属性Flatを持つ)なら,恒等式
が成り立つ.デフォルトの結合子が h 自体である場合は,演算は自然な方法で並列化される.次の例では全部の数が並列に加算される.
並列マッピングと反復子
このセクションのコマンドは,Wolfram言語での並列プログラミングの基本となるものである.
ParallelMap[f,h[e1,e2,…] | h[f[e1],[f[e2],…]を並列に評価する |
ParallelTable[expr,{i,i0,i1,di},{j,j0,j1,dj},…] | Table[expr,{i,i0,i1,di},{j,j0,j1,dj},…]を並列に構築する.並列化は最初の(最も外側の)反復子{i,i0,i1,di}で行われる |
ParallelSum[…],ParallelProduct[…] | 総和・総積を並列に計算する |
ParallelMap[f,h[e1,e2,…]]は f/@h[e1,e2,…]の並列版で,各 f[ei]を順にではなく並列に計算する.
副次的な影響
共有変数を使わない限り,実行される並列計算は完全に独立していて,互いに影響を及ぼし合うことはない.さらに,評価の一部として行われる変数への割当てなどの副次的な影響は失われる.並列評価によって唯一起ることは,結果が最後に返されるということである.
例
与えられた引数に正弦関数が適用される.各計算はリモートカーネルで行われる.
次の計算については並列評価を行うことの利点はほとんどない.Sin[0],Sin[π]等の式をリモートカーネルに送り,結果を回収するのに必要なオーバヘッドは,並列化で得られる利得と比べて大きくなる.
111…1という形の整数の因数分解にはより時間がかかる.したがってこの計算は並列化の意味がある.
別の方法として,ParallelTableを使うこともできる.11…1/i の因数の数のリストが生成される.
定義の自動配布
ParallelTable等の並列コマンドは事実上DistributeDefinitionsを使って自動的に必要な値と関数を配布する.
この自動配布は同じノートブック内でインタラクティブに定義したあらゆる関数と変数について(厳密には,デフォルトコンテキストの全シンボルについて)行われる.パッケージの関数等,他のコンテキストの定義は,自動的には配布されない.
定義の配布をより詳細に制御するために,以下のようにして自動配布を無効にする:
シンボルの定義を配布しないと,シンボルは通常並列サブカーネルから未評価のまま返され,その後マスターカーネルで評価される.コードはうまく動いているように見えるかもしれないが,実際は直列に評価される.kidは定義が配布された後,リモートカーネルで評価される.
自動並列化
Parallelize[cmd[list,arguments…]]は cmd が簡単に並列化できる方法でリストまたは長い式に作用するWolfram言語関数であるかどうかを判断し,自動的に並列化を行う.
この方法が常に並列化されるとは限らない.必要な場合にはメッセージが生成され,マスターカーネルで順次評価される.
