2014-10-20 19 views
6

Łączę MATLAB z C/C++ za pomocą MATLAB Engine API.Przyspieszenie wywołania Matlab Engine

W moim konkretnym przypadku MATLAB jest wykorzystywana do obliczenia czegoś, a wynik jest drukowany w C. Jednak w całej różnych testów na obu stronach zauważyłem znaczne straty wydajności w C.

Oto przykład z wywołań funkcji MATLAB :

tic; 
data = predictIM(data); 
toc; 

po stronie C zgłoszę podobne funkcje, co następuje:

iMod::Timer_T<high_resolution_clock> t; 

engPutVariable(ep, "data", dataContent); 
engEvalString(ep, "[posture] = predictIM(data);"); 

UT_NOTIFY(LV_DEBUG,"The execution took "<<t.seconds()); 

Moja implementacja zegar w C++ wygląda jak następująco:

template< class Clock > 
class Timer_T 
{ 
    typename Clock::time_point start; 
    public: 
     Timer_T() : start(Clock::now()) {} 
     typename Clock::duration elapsed() const { 
     return Clock::now() - start; 
     } 
     double seconds() const { 
     return elapsed().count() * 
      ((double)Clock::period::num/Clock::period::den); 
     } 
}; 

Powyższy kod MATLAB przebiega w temperaturze około 180 klatek na sekundę, w tym ustawieniu matrycy (data), podczas gdy kod C, tylko w 24 klatkach. Użyłem tic/toc do pomiaru czasu wykonania w MATLAB, podczas gdy moja własna implementacja timera jest używana po stronie C/C++.

Podczas profilowania aplikacji zauważyłem, że wywołania silnika MATLAB są wąskim gardłem. Wiem, że implementacja Linux MATLAB Engine używa nazwanych potoków do łączenia się z MATLAB i zastanawiałem się, czy istnieje sposób na przyspieszenie komunikacji MATLAB z jego silnikiem?

+0

To nie jest C, to C++. –

+0

Prawda. Przepraszam, że nie jest jasne. Zaimplementowałem silnik Matlab w C i obliczyłem czasy w C++ (gdzie używam dalej wyników Matlaba) – Dave

+1

@Dave: Myślę, że nie ma nic, co mógłbyś zrobić naprawdę, Engine API to kolejna warstwa, która dodaje narzut ze względu na wszystkie dane marshaling tam iz powrotem ... Zakładam, że łączysz się z MATLAB raz na starcie i ponownie używasz otwartego połączenia dla każdego obliczenia, prawda? Otwieranie i zamykanie połączenia z procesem MATLAB może być bardzo powolne. – Amro

Odpowiedz

1

Po pierwsze, nie jest sprawiedliwe mierzenie takiego silnika MATLAB. Należy tylko czas czas obliczeń tak samo, jak w programie MATLAB, jak to:

engPutVariable(ep, "data", dataContent);    // you should not time this 

iMod::Timer_T<high_resolution_clock> t; 
engEvalString(ep, "[posture] = predictIM(data);");  // time this only for fair 
UT_NOTIFY(LV_DEBUG,"The execution took "<<t.seconds()); 

Faktycznie, z mojego doświadczenia, z systemem MATLAB i nazywając jego silnik w C/C++ powinny mieć podobną prędkością jak one faktycznie zależy Oprogramowanie MATLAB.

Po drugie, mam radę dotyczącą możliwego przyspieszenia. Należy otworzyć tylko pojedynczy silnik MATLAB w całym projekcie C/C++, zamiast tworzyć jeden dla każdego połączenia. W ten sposób:

int main() 
{ 
    // Open MATLAB engine for the whole project 
    Engine *ep = engOpen(NULL); 

    // Use it multiple times 
    for (int i=0; i<100; ++i){ 
     engEvalString(ep, ...); 
    } 

    // Close MATLAB engine 
    engClose(ep); 

    return 0; 
} 
+1

Włączyłem czas przesyłania zmiennych do obszaru roboczego Matlab, ponieważ znacznie spowalnia to czas wykonywania. W moim przypadku ustawienie matrycy 3x16 zajmuje 15 ms podczas jej używania, a obliczenie wyniku zajmuje 28 ms. Pobieranie wyniku zajmuje kolejne 20 ms. Dlatego mierzenie czasu ustawiania/otrzymywania macierzy wydaje się istotne dla ogólnej wydajności. W mojej implementacji miałem tylko jeden silnik Matlaba. – Dave