2
$\begingroup$

I have a function programed in C which I load in MMA with

Needs["NETLink`"]
MYlTNC = DefineDLLFunction["ltnc", path, "double", {"double", "double", "double", "double", "double"}]

It works nicely except when I want to use it within a ParallelTable command. It is as if its definition does not get sent to the kernels. Here is a short example:

t2 = MYlTNC[0.025, 10, 1.1, 1.1 + 5, 1.1];
Export["try.dat", t2]
FilePrint["try.dat"]

outputs the following string correctly

3.09128

but

ParallelTable[
  t2 = MYlTNC[0.025, 10, 1.1, 6.1, 1.1];
  Export["try.dat", t2],
  {10}];
FilePrint["try.dat"]

outputs the string

If[NETLink`DLL`Private`checkArgCount["ltnc", {0.025, 10, 1.1, 6.1, 1.1}, 5], Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper5`ltnc[0.025, 10, 1.1, 1.1 + 5, 1.1], $Failed]

If I replace ParallelTable with Table, it works fine again.

Is there a way to incorporate within the kernels the definition of the attached DLL?

$\endgroup$
7
  • 1
    $\begingroup$ Does it help if you evaluate ParallelEvaluate[ MYlTNC = DefineDLLFunction["ltnc", path, "double", {"double", "double", "double", "double", "double"}] ] before the ParallelTable? $\endgroup$ Commented Apr 19, 2020 at 21:55
  • $\begingroup$ And also ParallelNeeds["NETLink`"] before that. $\endgroup$
    – Szabolcs
    Commented Apr 19, 2020 at 22:13
  • 1
    $\begingroup$ No, although the output has slighly changed to Wolfram`NETLink`DynamicDLLNamespace`DLLWrapper5`ltnc[0.025, 10, 1.1, 6.1, 1.1]. $\endgroup$ Commented Apr 19, 2020 at 22:23
  • 1
    $\begingroup$ It seems that a sequence of LaunchKernels[] ParallelNeeds["NETLink`"]DistributeDefinitions[path, MYlTNC] ParallelEvaluate[ MYlTNC = DefineDLLFunction["ltnc", path, "double", {"double", "double", "double", "double", "double"}]] does it. Any reason for that? $\endgroup$ Commented Apr 19, 2020 at 22:40
  • $\begingroup$ Well, apparently, the subkernels were lacking some important piece of information. Without ParallelNeeds["NETLink`"], they do not know the framework behind DefineDLLFunction. ParallelTable can auto-distribute symbols that appear in its body. But apparently, the symbols must be explicit. Moreover ParallelEvaluate makes sure that the DLL is loaded into each subkernel. Otherwise, each subkernel might request the main kernel to evaluate this function each time ot appears which would defeat the purpose of parallelization. $\endgroup$ Commented Apr 20, 2020 at 8:31

1 Answer 1

2
$\begingroup$

Well, apparently, the subkernels were lacking some important piece of information. ParallelTable can auto-distribute symbols that appear in its body, but the symbols must be explicit. "NETLink`" contains many other symbols onto which DefineDLLFunction references. In addition, "NETLink`" might have to load also a couule of library functions. Running

ParallelNeeds["NETLink`"]

guarantees that this package is loaded correctly on each subkernel. If a not so recent version of Mathematica is used, it might be necessary to execute also

DistributeDefinitions[path, MYlTNC]

in order to tell each kernel from where to read the DLLs. (IIRC, this is obsolete with Mathematica newer than 11.x.)

Afterwards,

ParallelEvaluate[MYlTNC = DefineDLLFunction["ltnc", path, "double", {"double",   "double", "double", "double", "double"}]]

loads the DLL into each subkernel separately. If you do not execute this, each subkernel might request the main kernel to evaluate this function each time it appears. This would defeat the purpose of parallelization.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.