Matlab引擎在并行循环中的应用

9

我在并行化的代码中使用多个Matlab引擎时遇到了一些问题。我可以成功地使用engOpenSingleUse生成多个引擎,但无法与多个引擎通信(即调用engPutVariable失败)。

像往常一样,这里有一个最小化的(VS)示例:

#include "stdafx.h"
#include <engine.h>
#include <omp.h>

int _tmain(int argc, _TCHAR* argv[])
{
//First spawn the matlab engine sessions
Engine *m_Engines[2];
for (int i = 0; i < 2; i++)
{
    m_Engines[i] = engOpenSingleUse(NULL, NULL, NULL);
}

//Then spawn the worker threads...
#pragma omp parallel num_threads(2)
{   
    // Allocate an engine to each thread
    int thread_num = omp_get_thread_num();
    Engine *thisEngine = m_Engines[thread_num];

    #pragma omp for
    for (int i = 0; i < 10000; i++)
    {
        // Create an mxArray and stick some data in it
        mxArray* mM = NULL;
        mM = mxCreateDoubleMatrix(1, 1, mxREAL);
        double data[1] = { 1.0 };
        memcpy((void *)mxGetPr(mM), (void *)data, sizeof(data));

        // Send it across to matlab
        engPutVariable(thisEngine, "A", mM);
        // Run some algorithm
        engEvalString(thisEngine, "A=A+1;");
        // Retrieve result
        mM = engGetVariable(thisEngine, "A");

        // Get it out of the mxarray
        double A = *mxGetPr(mM);
    }
}

return 0;
}

有什么想法吗?我正在使用Matlab R2012b,操作系统为Win x64。

4
请将 engOpenSingleUse 的调用放在并行区域内。请注意,MATLAB 引擎函数不是线程安全的,因此在调用它们时需要小心(即需要同步)。 - Hristo Iliev
可能是Matlab引擎API的线程安全性的重复问题。 - m7913d
1个回答

1

如您问题下方所述,如果您故意从多个线程调用非线程安全的闭源库的函数且没有同步,则行为是不可预测的,因此应避免这样做。一个可能的想法是将对MATLAB引擎的调用跨越多个进程进行,但请注意,这可能会增加复杂性(需要进程间同步)并降低性能。

顺便提一下,C++11及更高版本的用户应使用新的MATLAB Engine API for C ++进行编程。请注意,engOpenSingleUse在新API中没有等效的函数,至少不是显式的(最接近的替代函数是matlab::engine::startMATLAB)。


1
如果您在没有同步的情况下从多个线程故意调用非线程安全的库函数,那么行为是不可预测的。您可以从该句中删除“闭源”,并仍然是正确的。我不确定为什么需要在那里指定它。 - Cris Luengo
@Chris 当然,你是对的。我想强调的是,即使没有访问源代码,你也无法预测将发生什么(也就是说,你实际上是在玩一个黑盒子)。 - JtTest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接