MathLinkベースの関数の場合、(Windowsの場合)2つのことを行う必要があります。MLAbort
アボートをチェックするために使用することとMLCallYieldFunction
、プロセッサを一時的に生成するためにを呼び出すことです。どちらも、Todd GayleyによるMathLinkチュートリアルで説明されており、ここから入手できます。
以前の回答のビットを使用して、素数を計算するためのサンプルコードを次に示します(非効率的な方法ですが、これが説明のためにここで必要なものです)。
code =
"
#include <stdlib.h>
extern void primes(int n);
static void yield(){
MLCallYieldFunction(
MLYieldFunction(stdlink),
stdlink,
(MLYieldParameters)0 );
}
static void abort(){
MLPutFunction(stdlink,\" Abort \",0);
}
void primes(int n){
int i = 0, j=0,prime = 1, *d = (int *)malloc(n*sizeof(int)),ctr = 0;
if(!d) {
abort();
return;
}
for(i=2;!MLAbort && i<=n;i++){
j=2;
prime = 1;
while (!MLAbort && j*j <=i){
if(i % j == 0){
prime = 0;
break;
}
j++;
}
if(prime) d[ctr++] = i;
yield();
}
if(MLAbort){
abort();
goto R1;
}
MLPutFunction(stdlink,\"List\",ctr);
for(i=0; !MLAbort && i < ctr; i++ ){
MLPutInteger(stdlink,d[i]);
yield();
}
if(MLAbort) abort();
R1: free(d);
}
";
およびテンプレート:
template =
"
void primes P((int ));
:Begin:
:Function: primes
:Pattern: primes[n_Integer]
:Arguments: { n }
:ArgumentTypes: { Integer }
:ReturnType: Manual
:End:
";
プログラムを作成するためのコードは次のとおりです(前の回答から取得、わずかに変更):
Needs["CCompilerDriver`"];
fullCCode = makeMLinkCodeF[code];
projectDir = "C:\\Temp\\MLProject1";
If[! FileExistsQ[projectDir], CreateDirectory[projectDir]]
pname = "primes";
files = MapThread[
Export[FileNameJoin[{projectDir, pname <> #2}], #1,
"String"] &, {{fullCCode, template}, {".c", ".tm"}}];
ここで、それを作成します。
In[461]:= exe=CreateExecutable[files,pname];
Install[exe]
Out[462]= LinkObject["C:\Users\Archie\AppData\Roaming\Mathematica\SystemFiles\LibraryResources\
Windows-x86-64\primes.exe",161,10]
そしてそれを使用します:
In[464]:= primes[20]
Out[464]= {2,3,5,7,11,13,17,19}
In[465]:= primes[10000000]
Out[465]= $Aborted
後者の場合、Alt+"を使用しました。" 計算を中止します。への呼び出しを含めないと、これは正しく機能しないことに注意してくださいyield
。
一般的なイデオロギーは、大きなループなど、すべての高価な計算をチェックしMLAbort
て呼び出す必要があるというものです。おそらく、上記のように内部ループに対してそれを行うのはやり過ぎです。MLCallYieldFunction
試してみることができることの1つは、Cプリプロセッサ(マクロ)を使用してボイラープレートコードを因数分解することです。