如何使外部Mathematica功能可以中断?

前端之家收集整理的这篇文章主要介绍了如何使外部Mathematica功能可以中断?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
I had an earlier question about integrating Mathematica with functions written in C++.

这是一个后续问题:

如果计算时间太长,我希望能够使用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&C++相关文章