Sza*_*lcs 4 wolfram-mathematica mathematica-8
有没有人在远程并行内核中使用 Mathematica 的 C 扩展(LibraryLink 或 MathLink——目前我正在使用 LibraryLink)?
简而言之:当子内核在远程机器上运行时,如何在并行和非并行评估中透明地使用 LibraryLink 定义的函数(请参阅CreateLibrary和LibraryFunctionLoad)?
我找了一些设置步骤,这将让我有一个libraryFun函数(用C语言编写),可无论是通常称为libraryFun[args],或并行(两者的Parallelize@Table[libraryFun[arg], {arg, 0, 100}]和相同的ParallelTable[]时候subkernels在远程机器上运行)。
如果我也没有遇到问题,远程运行主内核也可能会更好。
与此同时,我取得了一些进展。我会在这里描述它。
首先,ParallelEvaluate将对所有并行内核中的表达式求值。如果 C 扩展的源文件被复制到远程机器,我们可以像这样在那里编译它们:
ParallelNeeds["CCompilerDriver`"]
k1 = First@Kernels[]
ParallelEvaluate[SetDirectory["/path/to/source/files"]]
ParallelEvaluate[CreateLibrary["sourefile", "myLibrary"]]
Run Code Online (Sandbox Code Playgroud)
此操作只需执行一次。我假设该库已经在主内核机器上编译。
在此之后,在所有后续会话中,我们可以FindLibrary在主计算机和远程计算机上使用来加载库。
LibraryFunctionLoad[myFun = FindLibrary["myLibrary"], "fun", ...]
ParallelEvaluate[myFun = LibraryFunctionLoad[FindLibrary["myLibrary"], "fun", ...]]
Run Code Online (Sandbox Code Playgroud)
麻烦来了。 由于路径myFun不同,在主内核和并行内核中会有不同的值。
所以问题是:如何确保myFun主内核和并行内核之间的值不会意外同步?
我将在一个孤立的例子中展示这可能是如何意外发生的:
In[1]:= LaunchKernels[2]
Out[1]= {KernelObject[1, "local"], KernelObject[2, "local"]}
Run Code Online (Sandbox Code Playgroud)
x在主内核中设置值:
In[2]:= x = 1
Out[2]= 1
Run Code Online (Sandbox Code Playgroud)
请注意,它在远程内核中也获得相同的值:
In[3]:= ParallelEvaluate[x]
Out[3]= {1, 1}
Run Code Online (Sandbox Code Playgroud)
x在并行内核中设置不同的值并验证它们是否保留它:
In[4]:= ParallelEvaluate[x = 2]
Out[4]= {2, 2}
In[5]:= {x, ParallelEvaluate[x]}
Out[5]= {1, {2, 2}}
Run Code Online (Sandbox Code Playgroud)
现在“无辜地”使用Parallelize包含以下内容的内容x:
In[6]:= Parallelize[Table[x, {10}]]
Out[6]= {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
Run Code Online (Sandbox Code Playgroud)
看看x主内核和子内核之间的值是如何重新同步的。
In[7]:= {x, ParallelEvaluate[x]}
Out[7]= {1, {1, 1}}
Run Code Online (Sandbox Code Playgroud)
新问题是:如何防止某个符号在主内核和子内核之间自动同步?
我希望这回答了你的问题:
目前,我假设主内核和并行内核在同一个架构上,对我来说是 Windows 7。首先你编译一个函数;你可以做到这一点以外的Mathematica使用C编译器在数学,或直接:
f = Compile[{x}, x^2, CompilationTarget -> "C"]
Run Code Online (Sandbox Code Playgroud)
您可以通过查看检查InputForm的f地方,产生的dll位于:
f // InputForm
Run Code Online (Sandbox Code Playgroud)
给出类似的东西:
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]]
Run Code Online (Sandbox Code Playgroud)
您可以将此文件复制到并行(可能是远程)内核可以找到它的位置,例如:
CopyFile["C:\\Users\\arnoudb\\AppData\\Roaming\\Mathematica\\ApplicationData\\CCompilerDriver\\BuildFolder\\arnoudb2win-3316\\compiledFunction1.dll",
"c:\\users\\arnoudb\\compiledFunction1.dll"]
Run Code Online (Sandbox Code Playgroud)
然后您可以在所有并行内核中加载库,如下所示:
ParallelEvaluate[
ff = LibraryFunctionLoad["C:\\users\\arnoudb\\compiledFunction1.dll",
"compiledFunction1", {Real}, Real]
]
Run Code Online (Sandbox Code Playgroud)
并检查这是否有效:
ParallelEvaluate[ff[3.4]]
Run Code Online (Sandbox Code Playgroud)
这{11.56,11.56}对我来说是回报。
如果并行内核在不同的架构上,您将需要为该架构编译 C 代码(或Compile[..., CompilationTarget->"C"]在并行内核上评估)。
| 归档时间: |
|
| 查看次数: |
639 次 |
| 最近记录: |