リモート定義
並列カーネルはマスターカーネルで定義されている値にも,ローカルで定義されている関数にもアクセスすることができない.
Wolfram言語にはコマンドDistributeDefinitionsが含まれており,これにより全並列カーネルへのローカルの変数と定義の移送が簡単になる.この方法の主な利点は,リモートカーネルにアプリケーションパッケージをインストールする必要がないということである.すべての定義は,既存の接続を使ってリモートカーネルに送信される.
定義を分配する
| DistributeDefinitions[s1,s2,…] | シンボル si の全定義をすべてのリモートカーネルに分配する |
| DistributeDefinitions["Context`"] | 特定のコンテキストの全シンボルの定義を分配する |
DistributeDefinitionsはシンボルの評価を避けるために属性HoldAllを持つ.
DistributeDefinitionsはOwnValues,DownValues,SubValues,UpValues,DefaultValues,NValuesのような定義をエキスポートする.
DistributeDefinitionsはリモートシンボルの属性を,Protected,Locked等の属性を除き,ローカルで定義された属性と等しくなるように設定する.
リモート側に存在していた古い定義はすべて,新しい定義が行われる前にクリアされる.
例
ParallelEvaluate[ $ProcessID]var = 5;SetAttributes[func, Listable]
func[r_] := r ^ 2ParallelEvaluate[Names["var"]]ParallelEvaluate[func[var]]このように見えるのは,関数と変数がリモートカーネルで定義されていないので,リモートカーネルは未評価の式func[var]を返すからである.マスターカーネルは返された結果をさらに評価するが,これは順次行われる.
リモートおよびローカルでの評価の違いが明らかになる例は簡単に作成できる.
Head[var]ParallelEvaluate[Head[var]]DistributeDefinitions[var, func]ParallelEvaluate[Head[var]]定義の自動分配
Parallelize,ParallelTable,ParallelSum,…等のより高レベルの並列コマンドは,引数として現れるシンボルの定義を自動的に分配する.
f[x_, y_] := x ^ y
{m, n} = {4, 2};ParallelTable[f[i, j], {i, m}, {j, n}]この自動分配は同じノートブック内でインタラクティブに定義したあらゆる関数と変数について(厳密には,デフォルトコンテキストの全シンボルについて)行われる.パッケージの関数等,他のコンテキストの定義は,自動的には分配されない.
ctx`s := $KernelIDParallelTable[ctx`s, {4}]DistributeDefinitions[ctx`s];ParallelTable[ctx`s, {4}]コンテキストを分配する
DistributeDefinitions["Context`"]は全シンボルの定義をすべて指定のコンテキストにエキスポートする.そのため,以下を使ってインタラクティブに入力されたすべての定義をリモートカーネルに知らせることができる.
DistributeDefinitions["Global`"]ロードしたパッケージのコンテキストをエキスポートしても,リモートカーネルでは各リモートカーネルでパッケージをロードしたのと同じ効果が得られないことがある.これは,パッケージをロードすると,ある初期化が行われ,これにより他のコンテキスト(プライベートコンテキスト等)の補助的な関数も定義されることがあるからである.また,パッケージは追加の補助的なパッケージもロードすることがあり,そのようなパッケージは独自のコンテキストを構築する.
DistributeDefinitions["Context`"]はリモートカーネルで使うように明示的に設定した定義のコンテキストのエキスポートに便利である.パッケージのリモートのロードのために別のコマンドParallelNeedsがある.
Parallel`Developer`ClearKernels[]はリモートカーネルのGlobal`コンテキストの定義をすべてクリアする.
リモートカーネルにパッケージをロードする
| ParallelNeeds["Context`"] | 利用できる全並列カーネルでNeeds["Context`"]を評価する |
ParallelNeeds["Context`"]は基本的にはParallelEvaluate[Needs["Context`"]]と同じであるが,これは記憶され,その後新しく起動したリモートカーネルも初期化される.
ロードしたパッケージのコンテキストをエキスポートしても,リモートカーネルでは各リモートカーネルでパッケージをParallelNeeds[]でロードしたのと同じ効果が得られないことがある.これは,パッケージをロードすると,ある初期化が行われ,これにより他のコンテキスト(プライベートコンテキスト等)の補助的な関数も定義されることがあるからである.また,パッケージは追加の補助的なパッケージもロードすることがあり,そのようなパッケージは独自のコンテキストを構築する.
Needs["FiniteFields`"]ParallelNeeds["FiniteFields`"];マスターカーネルで利用できるWolfram言語パッケージは古いバージョンのWolfram言語のリモートカーネルでは利用できないことがある.
例:行列の固有値
定義
prec = 18;mat[n_] := RandomReal[{-1, 1}, {n, n}, WorkingPrecision -> prec]tf[n_] := Timing[Eigenvalues[mat[n]]][[1]]DistributeDefinitions[tf]実行例
ParallelMap[tf, {50, 60, 70, 80}]ParallelEvaluate[tf[70]]