gpt4 book ai didi

c - 如何使外部 Mathematica 函数可中断?

转载 作者:太空狗 更新时间:2023-10-29 17:08:27 25 4
gpt4 key购买 nike

I had an earlier question about integrating Mathematica with functions written in C++.

这是一个后续问题:

如果计算花费的时间太长,我希望能够使用Evaluation > Abort Evaluation 中止计算。答案中建议的哪些技术可以实现可中断的基于 C 的扩展功能? C端如何实现“可中断性”?

我需要以一种既不会破坏它也不会破坏 Mathematica 内核的方式使我的函数可中断(即应该可以在它被中断后从 Mathematica 再次调用该函数)

最佳答案

对于基于 MathLink 的函数,您必须做两件事(在 Windows 上):使用 MLAbort 检查中止,并调用 MLCallYieldFunction 以让出处理器暂时地。两者都在 Todd Gayley 的 MathLink 教程中进行了描述,可用 here .

使用我之前回答中的位,这里是一个计算素数的示例代码(以一种低效的方式,但这是我们需要在这里进行说明的代码):

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,例如大循环等。也许,对内部循环这样做不过,我在上面所做的有点矫枉过正。您可以尝试做的一件事是使用 C 预处理器(宏)将样板代码分解掉。

关于c - 如何使外部 Mathematica 函数可中断?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8279541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com