有没有人有使用远程并行内核对 Mathematica 的 C 扩展(LibraryLink 或 MathLink——目前我正在使用 LibraryLink)的经验?
简而言之:当子内核在远程机器上运行时,如何在并行和非并行评估中透明地使用 LibraryLink 定义的函数(请参阅CreateLibrary和LibraryFunctionLoad )?
我正在寻找一些设置步骤,这些步骤将允许我拥有一个函数(用 C 编写),当子内核在远程计算机上运行时,该libraryFun
函数可以正常调用,也可以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}}
新问题是:如何防止某个符号在主内核和子内核之间自动同步?