2013-02-26 4 views
2

Редакция 2: Проблема решена, см. Мой ответ.Асинхронный вызов engEvalString MATLAB

Я пишу программу на С ++, которая общается с MATLAB через Engine API. Приложение C++ работает в Windows 7 и взаимодействует с MATLAB 2012b (32-разрядная версия).

Я хотел бы заняться трудоемким обращением к двигателю MATLAB, используя engEvalString, но не могу понять, как сделать асинхронный вызов. Обратный вызов не требуется (но было бы неплохо, если это было возможно).

Ниже приведен минимальный пример того, что не работает.

#include <boost/thread.hpp> 

extern "C" { 
    #include <engine.h> 
} 

int main() 
{ 
    Engine* eng = engOpen(""); 
    engEvalString(eng,"x=10"); 
    boost::thread asyncEval(&engEvalString,eng,"y=5"); 
    boost::this_thread::sleep(boost::posix_time::seconds(10)); 
    return 0; 
} 

После запуска этой программы, я переключаюсь на окно двигателя MATLAB и найти:

» x 
x = 
    10 
» y 
Undefined function or variable 'y'. 

Таким образом, кажется, что второй вызов, который должен положить у = 5, никогда не обрабатывается MATLAB двигатель.

Поток определенно работает, вы можете проверить это, переместив вызов engEvalString в локальную функцию и вместо этого запустив это как поток.

Я действительно в тупике и буду благодарен за любые предложения!

EDIT: Как указал Шафик в своем ответе, двигатель не является потокобезопасным. Я не думаю, что это должно быть проблемой для моего случая использования, поскольку вызовы, которые мне нужно сделать, составляют ~ 5 секунд друг от друга, для расчета требуется 2 секунды. Причина, по которой я не могу дождаться этого вычисления, заключается в том, что приложение C++ является «средним жестким» контроллером реального времени, который должен отправлять команды с частотой 50 Гц. Если этот показатель опускается ниже 30 Гц, робот будет принимать сетевые проблемы и закрыть соединение.

ответ

1

Итак, я понял, проблема, но хотелось бы, если бы кто-то может объяснить, почему !

следующие работы:

#include <boost/thread.hpp> 

extern "C" { 
#include <engine.h> 
} 

void asyncEvalString() 
{ 
    Engine* eng = engOpen(""); 
    engEvalString(eng,"y=5"); 
} 

int main() 
{ 
    Engine* eng = engOpen(""); 
    engEvalString(eng,"x=10"); 
    boost::thread asyncEvalString(&asyncEvalString); 
    boost::this_thread::sleep(boost::posix_time::seconds(1)); 
    engEvalString(eng,"z=15"); 
    return 0; 
} 

Как вы можете видеть, что вам нужно, чтобы получить новый указатель на двигатель в новом потоке.Указатель, возвращаемый в asyncEvalString отличается от исходного указателя, возвращаемого engOpen в основной функции, однако оба указателя продолжает работать без проблем:

» x 
x = 
    10 
» y 
y = 
    5 
» z 
z = 
    15 

Наконец, для решения проблемы безопасности потоков, мьютекс может быть установлен вокруг вызовов engEvalString, чтобы гарантировать, что только один поток использует двигатель в любой момент времени. Функция asyncEvalString также может быть изменена, чтобы вызвать функцию обратного вызова после завершения функции engEvalString.

Я бы хотел, чтобы кто-то объяснил, почему это решение работает. Поток разделяет кучу выделенной памяти процесса и может получать доступ к памяти на стеках других потоков (?), Поэтому я не понимаю, почему первый Engine* был неожиданно недействителен при использовании в отдельном потоке.

+0

Я хотел бы добавить, что вызов engOpen ("") занимает относительно много времени, поэтому, когда это возможно, Engine * следует кэшировать для повторного использования в том же потоке. Если я кэширую значение для синхронных вызовов, я могу достичь скорости петли 50 Гц (с большим количеством другой сложной обработки, это примерно предел моего ноутбука), если я получу новый движок для каждого вызова, я могу только достичь 25 Гц. –

1

Так, согласно этому Mathworks документу он не поточно поэтому я сомневаюсь, что это будет работать:

http://www.mathworks.com/help/matlab/matlab_external/using-matlab-engine.html

и в соответствии с этим документом, engOpen вил новый процесс, который, вероятно, объяснить остальной части поведение, которое вы видите:

http://www.mathworks.com/help/matlab/apiref/engopen.html

Также см, темы и вилки, подумайте дважды, смешивая их:

http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them

+0

Хорошая точка в отношении безопасности потоков, однако расчетные вызовы, которые мне нужно сделать для MATLAB, расположены на расстоянии ~ 5 секунд друг от друга, причина, по которой она должна быть асинхронной, заключается в том, что программе (контроллеру для робота) необходимо отправлять команды каждые 20 мс и не может дождаться завершения вычисления. –

Смежные вопросы