4

Mathematica の C 拡張機能 (LibraryLink または MathLink -- 現在は LibraryLink を使用しています) をリモートの並列カーネルで使用した経験のある人はいますか?

要するに、サブカーネルがリモート マシンで実行されている場合、並列評価と非並列評価の両方で、LibraryLink で定義された関数 ( CreateLibraryおよびLibraryFunctionLoadを参照) を透過的に使用するにはどうすればよいでしょうか?

サブカーネルがリモートマシンで実行されているときに、通常は として、または並行して ( と同じ)呼び出すことできるlibraryFun関数 (C で記述) を使用できるようにするセットアップ手順を探しています。libraryFun[args]Parallelize@Table[libraryFun[arg], {arg, 0, 100}]ParallelTable[]

メインカーネルをリモートで実行することも、問題がなければもっと良いかもしれません。


アップデート

その間、私はいくつかの進歩を遂げました。ここで説明します。

まず、ParallelEvaluateすべての並列カーネルで式を評価します。C 拡張機能のソース ファイルがリモート マシンにコピーされている場合は、次のようにコンパイルできます。

ParallelNeeds["CCompilerDriver`"]
k1 = First@Kernels[]
ParallelEvaluate[SetDirectory["/path/to/source/files"]]
ParallelEvaluate[CreateLibrary["sourefile", "myLibrary"]]

これは一度だけ行う必要があります。ライブラリはメイン カーネル マシン上で既にコンパイルされていると仮定します。

この後、後続のすべてのセッションでFindLibrary、メイン マシンとリモート マシンの両方で使用してライブラリをロードできます。

LibraryFunctionLoad[myFun = FindLibrary["myLibrary"], "fun", ...]
ParallelEvaluate[myFun = LibraryFunctionLoad[FindLibrary["myLibrary"], "fun", ...]]

そして、ここで問題が発生します。 パスが異なるためmyFun、メイン カーネルと並列カーネルで値が異なります。

問題は、 の値がメイン カーネルと並列カーネルの間で誤って同期されないようにするにはどうすればよいかということです。myFun

これが偶発的にどのように発生する可能性があるかを、孤立した例で示します。

In[1]:= LaunchKernels[2]
Out[1]= {KernelObject[1, "local"], KernelObject[2, "local"]}

xメインカーネルの設定値:

In[2]:= x = 1
Out[2]= 1

リモートカーネルでも同じ値を取得することに注意してください。

In[3]:= ParallelEvaluate[x]
Out[3]= {1, 1}

x並列カーネルで別の値を設定し、それが保持されていることを確認します。

In[4]:= ParallelEvaluate[x = 2]
Out[4]= {2, 2}

In[5]:= {x, ParallelEvaluate[x]}
Out[5]= {1, {2, 2}}

Parallelizeを含むものに「無邪気に」使用するようになりましたx:

In[6]:= Parallelize[Table[x, {10}]]
Out[6]= {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}

そして、メインカーネルとサブカーネルの間で の値がどのようxに再同期されるかを確認してください。

In[7]:= {x, ParallelEvaluate[x]}
Out[7]= {1, {1, 1}}

新しい質問は、特定のシンボルがメインカーネルとサブカーネルの間で自動同期されないようにするにはどうすればよいですか?

4

2 に答える 2

5

これがあなたの質問に答えることを願っています:

ここでは、メイン カーネルと並列カーネルが同じアーキテクチャ (私にとっては Windows 7) にあると仮定します。まず、関数をコンパイルします。これは、C コンパイラを使用してMathematicaの外部で行うことも、Mathematica で直接行うこともできます。

f = Compile[{x}, x^2, CompilationTarget -> "C"]

生成された dll が配置されている場所InputFormを調べることで調べることができます。f

f // InputForm

次のようなものを与えます:

CompiledFunction[{8, 8., 5468}, {_Real}, {{3, 0, 0}, {3, 0, 1}}, {}, {0, 0, 2, 0, 0}, {{40, 
56, 3, 0, 0, 3, 0, 1}, {1}}, Function[{x}, x^2], Evaluate,
LibraryFunction["C:\\Users\\arnoudb\\AppData\\Roaming\\Mathematica\\ApplicationData\\CCompilerDriver\\BuildFolder\\arnoudb2win-5184\\compiledFunction0.dll", 
"compiledFunction0", {{Real, 0, "Constant"}}, Real]]

このファイルを、並列 (おそらくリモート) カーネルが見つけられる場所にコピーできます。たとえば、次のようになります。

CopyFile["C:\\Users\\arnoudb\\AppData\\Roaming\\Mathematica\\ApplicationData\\CCompilerDriver\\BuildFolder\\arnoudb2win-3316\\compiledFunction1.dll",
"c:\\users\\arnoudb\\compiledFunction1.dll"]

次に、次のようにすべての並列カーネルにライブラリをロードできます。

ParallelEvaluate[
 ff = LibraryFunctionLoad["C:\\users\\arnoudb\\compiledFunction1.dll",
 "compiledFunction1", {Real}, Real]
]

そして、これが機能するかどうかを確認します:

ParallelEvaluate[ff[3.4]]

それは私のために戻ります{11.56,11.56}

並列カーネルが異なるアーキテクチャ上にある場合は、そのアーキテクチャ用に C コードをコンパイルする (またはCompile[..., CompilationTarget->"C"]並列カーネルで を評価する) 必要があります。

于 2012-01-05T23:18:54.163 に答える
1

上記の更新で私の質問に対する解決策を見つけたようです。動作しているようですが、壊れやすいものではないことはまだ確認できません.

解決策は、同期させたくないシンボルを別のコンテキストに入れることです。c`x私の例で の代わりに使用すると、 の内部で使用されたときにxの値が同期されなくなります。次に、このコンテキストを に追加して、シンボルに簡単にアクセスできるようにします。xParallelize$ContextPath

これを行う最も便利な方法は、おそらく、すべての定義をパッケージに入れ、 を使用してライブラリ関数をロードすることLibraryFunctionLoad[FindLibrary[...], ...]です。これが機能するには、ローカル マシンとリモート マシンの両方で最初にライブラリを手動でコンパイルする必要がありますが、パッケージ コードはメインとサブカーネルの両方でまったく同じにすることができます。


含まれていない変数が自動同期されないこと$Context保証されていることを誰かが確認できるかどうか、私はまだ興味があります。

更新こちらで確認済みです。

于 2012-01-06T14:45:35.407 に答える