WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

multithreading Overhead

 

Bluesmaster
Forum-Century

Forum-Century



Beiträge: 203
Anmeldedatum: 13.11.11
Wohnort: Gera
Version: 2012a
     Beitrag Verfasst am: 01.08.2012, 14:20     Titel: multithreading Overhead
  Antworten mit Zitat      
Hallo,

Ich bräuchte für eine GUI eine parallelisierung von rechnen und
interagieren. Die "Parallel Computing Toolbox" liefert z.B. den batch()-command

Aber:
Code:

tic;     rand(100);                                                   toc

tic;     j = batch(@rand, 1, {100});    wait(j) ;        toc


ca 13 Sekunden bis der Thread gestartet ist. Na danke auch Rolling Eyes


Frage:

1. kann man diesen Overhead in den zentel-Sekundenbereich minimieren?

2. Falls nicht gibt es irgendeinen Java/ Mex oder ähnlichen Workaround
für einen schnell startenden Thread, der möglichst Zugriff auf die
globalen Variablen meines Workspaces hat?

das wäre echt dringend, da ich sonst vielleicht mein ganzes Projekt an den Nagel hängen müsste Sad

Gruß

Blues
Private Nachricht senden Benutzer-Profile anzeigen


flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.08.2012, 11:16     Titel:
  Antworten mit Zitat      
Du kannst doch in einem Mex File jede Art von Threading benutzen, das Du brauchst (pThreads, OpenMP, mThreads, Boost Thread....) und dann die Mex Routinen direkt aufrufen.

Andernfalls schreibe eine reine C/C++ Bibliothek, wie Du sie mit Threads brauchst und binde diese dann in Matlab via loadlibrary ein.

Wie man das nun konkret macht, ist abhängig von der Problemstellung und ggf weiteren Bedingungen, aber das Threading sollte imho das kleine Problem sein
Private Nachricht senden Benutzer-Profile anzeigen
 
Bluesmaster
Themenstarter

Forum-Century

Forum-Century



Beiträge: 203
Anmeldedatum: 13.11.11
Wohnort: Gera
Version: 2012a
     Beitrag Verfasst am: 02.08.2012, 12:36     Titel:
  Antworten mit Zitat      
danke flashpixx, ich bin leider etwas schwachbrüstig was mex/c++ angeht.

Das erste was ich gelesen habe hat mich eher etwas abgeschreckt:

http://www.gomatlab.de/multithreadi.....light,multithreading.html

Da sagt Jan:

"Matlab ist single-threaded. Ein Aufrufs von mexCallMATLAB in einem neuen erzeugten Thread muss deshalb scheitern. "

Demzufolgen hab ich auch keinen Zugriff auf den Workspace und meine Matlabfunktionen. Den bräuchte ich aber Sad .


Hätte dazu jemand einen Vorschlag? Vielleicht auch wie man den Overhead doch aus der Parallel Computing Toolbox raus kriegt?

Gruß

Blues
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.08.2012, 12:49     Titel:
  Antworten mit Zitat      
Einen Overhead für die Thread Instantiierung hast Du immer, selbst wenn Du es native machen würdest. Weiterhin wirst Du, wenn Du einen Datenblock durch mehrere Threads bearbeiten lässt, Dich unweigerlich mit Mutex befassen müssen ( http://de.wikipedia.org/wiki/Mutex ) bzw. wenn die Daten zentral gehalten werden sollen mit einem "Local Storage" ( http://en.wikipedia.org/wiki/Thread-local_storage ). Ich rate ganz dringend davon ab, "mal eben so bisschen Threading zu programmieren", das wird sehr viele Probleme machen.

Da Matlab ja als Singlethread läuft wäre mein Vorschlag die Daten in eine native Bibliothek hinein zu reichen und dort dann eben via Multithreading die Daten zu verarbeiten und nach der Bearbeitung wieder aus der Bibliothek zurück in Matlab zu reichen. Ob man da nun eine blocking bzw non-blocking Struktur macht ist unerheblich. Ich würde da ganz konkret die Bibliothek unabhängig von Matlab entwerfen und dann lediglich einen Mex-Wrapper erstellen, um die Bibliothekaufrufe in / aus Matlab zu ermöglichen. Dann musst Du das Mex File compilieren und gegen Deine Bibliothek linken. Konkret bedeutet das, dass nicht die Bibliothek bzw. der Thread auf Matlab zugreifst, sondern Matlab aktiv die Daten an die Bibliothek gibt bzw. von der Bibliothek holt.

Ich verweise direkt einmal auf Boost Thread ( http://www.boost.org/doc/libs/1_50_0/doc/html/thread.html ), da Du damit cross-plattform das Threading erzeugen kannst. Es gibt dort sehr schöne Beispiele, die einem genau zeigen, wie Threads erzeugt werden müssen. Mutex bzw. Shared-Mutex und Local-Storage werden direkt als fertige Strukturen mitgeliefert.
Private Nachricht senden Benutzer-Profile anzeigen
 
Bluesmaster
Themenstarter

Forum-Century

Forum-Century



Beiträge: 203
Anmeldedatum: 13.11.11
Wohnort: Gera
Version: 2012a
     Beitrag Verfasst am: 02.08.2012, 13:12     Titel:
  Antworten mit Zitat      
Danke für die vielen nützlichen Infos.
Ich dachte mir schon das es nicht trivial wird.
Aber es ist unumgänglich für mein Vorhaben.

Ich werde mich wohl hineinarbeiten müssen. Ich habe ein paar Skizzen
im Kopf mit einer Lücke: Wie konkret funktioniert das zurückreichen der Daten?
Welcher mexBefehl wäre das und inwiefern wird er mit dem matlab-Thread dabei koordiniert?


Entschuldige diese Fragen, ich bin leider kein Informatiker und kann
im moment kaum c++

Gruß

Blues
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.08.2012, 13:51     Titel:
  Antworten mit Zitat      
Bluesmaster hat Folgendes geschrieben:

Ich werde mich wohl hineinarbeiten müssen. Ich habe ein paar Skizzen
im Kopf mit einer Lücke: Wie konkret funktioniert das zurückreichen der Daten?
Welcher mexBefehl wäre das und inwiefern wird er mit dem matlab-Thread dabei koordiniert?



Ich skizziere das Vorgehen einmal. Du erzeugst eine C Funktion:
Code:

#include <mex.h>
#include <yourlib.h>

int mexStartThread( int x ) {
   return your_lib_call(x);
}
 


Das wäre grob gesagt der Aufruf der Mex-Routine, die nichts anderes macht, als die Daten an die Bibliotheksfunktion zu übergeben und die Rückgabe wieder zurück zu liefern. In Matlab würde man dann einfach sagen
Code:

 x = StartThread( 5 );
 


Der Aufruf "your_lib_call" sorgt dann dafür, dass eben mehrere Thread erzeugt werden und gewartet wird, bis alle Threads beendet wurden (blocking Aufruf).
Code:

#include <boost/thread.hpp>
#include <boost/bind.hpp>

void threadrun( int x )
{
     do something with x
}


int your_lib_call( int x )
{
       boost::thread_group threadgroup;

        for(std::size_t i=0; i < boost::thread::hardware_concurrency(); ++i)
               threadgroup.create_thread( boost::bind( threadrun, x ) );

        threadgroup.join_all();

        return result;
}
 



In dem Aufruf "your_lib_call" wird dann eben anhand der Hardware eine Threadgruppe erzeugt, d.h. es werden so viele Thread generiert, die alle die Funktion "threadrun" bearbeiten, wie im System möglich ist. Das join_all wartet, bis alle in der Threadgruppe enthaltene Thread fertig sind mit der bearbeiten. Ein Thread ist "auch nur" eine Funktion, d.h. man kann da Daten hinein geben. Die Rückgabe der Funktion kann man über shared Variablen machen, das bedeutet, dass jeder Thread in einen gemeinsamen Bereich seine Daten ablegt.

Ich würde generell dazu raten C++ zu verwenden, weil man durch die Objektorientierung eine Kapselung der Daten erreicht, d.h. Deine Bibliothek besteht aus "einer" Klasse, die im Grunde nicht anderes macht als eben die Threads zu erzeugen, die Daten zu verarbeiten und die Daten zurück liefert. Durch die Boost Threads bist Du direkt auch cross-plattform, d.h. Deine Bibliothek wird auf Windows, Linux und OSX ohne weiteres laufen. Das wäre der eine Teil und diese Entwicklung ist völlig unabhängig von Matlab.

Als nächster Schritt musst Du dann Deine Funktion an Matlab "dran hängen", was hier dann mit Hilfe von Mex geschieht, d.h. Du musst mit Hilfe von Mex einen "Matlab Aufruf" erzeugen und innerhalb der Mex Funktion eben die Matlab spezifischen Datentypen in "generelle" C++ verständliche Datentypen umwandeln und dann rufst Du eben die Funktion Deiner Bibliothek auf mit den Parameter auf. Da dieser Aufurf "blockiert", wird die Mex Funktion erst weiter laufen, wenn eben alle Threads fertig gearbeitet haben. D.h. nach dem Aufruf kannst Du Dir aus der Bibliothek einfach die berechneten Daten holen und musst diese wieder zurück in die Matlabdatentypen konvertieren.

Ist eigentlich ganz einfach: Matlab ruft Mex Funktion mit Daten auf => Mex Funktion wandelt Matlabdaten in C/C++ Daten um und ruft Bibliotheksfunktion auf => Bibliotheksfunktion erzeugt Thread und macht was und wartet bis alles fertig ist => Mex Funktion läuft weiter und holt die Daten aus der Bibliothek und wandelt sie wieder zurück in Matlabdatentypen um

Ich weiss jetzt im Speziellen nicht, was Du alles benötigst, aber direkt einmal der Hinweis, dass die Boost auch Vektor und Matrixstrukturen direkt mit bringt, siehe http://www.boost.org/doc/libs/1_50_.....meric/ublas/doc/index.htm

Bluesmaster hat Folgendes geschrieben:

Entschuldige diese Fragen, ich bin leider kein Informatiker und kann im moment kaum c++


Wenn Du wirklich Threads brauchst, dann musst Du Dich leider mit einem Teil der Informatik befassen. Ich würde auch hier zu C++ raten, denn gerade mit der Boost hast Du eine Basis, die Dir wirklich schon sehr viel bietet. Threading ist nicht trivial und gerade die Nebenläufigkeit führt oft bei Anfängern zu Problemen, da Effekte auftreten können, die nicht unbedingt so gewollt sind.
Mein praktischer Tipp wäre, dass Du zuerst einmal die eine Basis für die Programmierung in C++ aufbaust. Dann würde ich empfehlen, dass Du die Bibliothek in Ruhe strukturiert generierst und mit Hilfe eine kleinen Beispiel C++ Programms auf Herz & Nieren testest. Wenn das dann alles klappt, würde ich dann abschließend die Mex Kapselung für Matlab bauen.
Ich habe hier jetzt einfach mal die Boost Threads genommen, natürlich müsste man anhand Deiner konkreten Problemstellung überlegen, ob man wirklich auf diese Art der Threadimplementierung setzt, evtl kann man das noch einmal durch denken. Ansonsten von mir der Hinweis, dass Threading nicht umbedingt dazu führt, dass das Problem "schneller" gelöst wird, oft liegen die Probleme im Algorithmus, d.h. wenn man den verändert braucht man kein Threading. Einen Algorithmus nehmen und dann diesen als Multithread Variante zu erstellen ist nicht trivial, weil man wissen muss, wie der Algorithmus real die Daten verarbeitet, d.h. bei ungenügender Kenntnis kann eine Multithread Variante sogar langsamer sein als eine Singlethread Variante.

Die Codebeispiele sind nur eine grobe Skizze des Ablaufes, d.h. die Details müsstest Du dann selbst anpassen
Private Nachricht senden Benutzer-Profile anzeigen
 
Bluesmaster
Themenstarter

Forum-Century

Forum-Century



Beiträge: 203
Anmeldedatum: 13.11.11
Wohnort: Gera
Version: 2012a
     Beitrag Verfasst am: 02.08.2012, 14:20     Titel:
  Antworten mit Zitat      
danke dir für die viele Arbeit die du dir gemacht hast. Für die ganzen
Ansätze werde ich ein paar Tage brauchen.

Die Lücke ist aber immer noch nicht ganz zu


Der Mex-Wrapper muss auf die Boost-Threads warten. Und genau das
muss ich vermeiden sonst stockt die GUI. Ich will nicht unbedingt
schneller werden, sondern eher entkoppeln.

Der Benutzer verschiebt bsp ein Matlab-Patch Objekt in Echtzeit und das
löst Rechenvorgänge aus die dem Benutzer etwas über die Verschiebung sagen.
Das kann dann auch ein paar Sekunden verzögert kommen. (nur eben nicht 13 Sekunden wie beider Parallel Computing Toolbox)

Der Thread müsste die Ergebnisse gewissermaßen selbstständig zurück nach
Matlab "impfen" damit Matlab sich in der zwischenzeit weiter um die Patchverschiebung kümmer kann.


Geht das? Matlab kurz unterbrechen und ihm Ergebnisse übergeben?
Oder zumindest die Ergebnisse irgendwo ablegen wo Matlab selbständig heran kommt?


vielen Dank nochmal
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.08.2012, 15:19     Titel:
  Antworten mit Zitat      
Bluesmaster hat Folgendes geschrieben:

Der Mex-Wrapper muss auf die Boost-Threads warten. Und genau das
muss ich vermeiden sonst stockt die GUI. Ich will nicht unbedingt
schneller werden, sondern eher entkoppeln.


hatte ich doch richtig gedacht, dann brauchst Du eine "non-blocking" Kommunikation etwa in der Art:
Code:

void mexStartThread( parameter )

boolean mexisThreadFinish()

void getThreadData( parameter )
 


Du rufst dann in Matlab das StartThread auf, das aber dann kein "join_all" hat, d.h. alle Threads werden gestartet und laufen. Nun musst Du Dir eben speichern, ob die Threads fertig sind (das macht man intern über eine zentrale Datenstruktur). Mit der Funktion isFinish kannst Du dann in Matlab prüfen, ob alle Threads fertig gearbeitet haben und wenn sie das haben, kannst Du dann getData aufrufen, das Dir dann die Daten an Matlab zurück liefert.

Bluesmaster hat Folgendes geschrieben:

Der Thread müsste die Ergebnisse gewissermaßen selbstständig zurück nach
Matlab "impfen" damit Matlab sich in der zwischenzeit weiter um die Patchverschiebung kümmer kann.


Das wird so nicht gehen, dann dafür müsstest Du aus dem C/C++ Kontext in Deine aktuell laufende Matlabsession greifen, was ich aus verschiedenen Gründen vermeinden würde. So wie ich es dargestellt habe, musst Du dann aktiv in Matlab fragen "sind die Threads fertig", kann man ja z.B. so machen

Code:

    while (allpatches_finish)
          do_next_patch

          if isThreadFinish
              getThreadData        
              StartThread( get_next_patch) ;
          end
    end
 



Bluesmaster hat Folgendes geschrieben:

Geht das? Matlab kurz unterbrechen und ihm Ergebnisse übergeben?


Da Du nicht weißt wie lange die Berechnung dauert, würde ich im Grunde die Daten einmal in Matlab alle soweit vorbereiten, dann komplett alle Daten an meine Mex Funktion geben und dann regelmäßig aus Matlab nach fragen, ob alles fertig ist.
Da Matlab eben Singelthread ist, müsstest Du, wenn Du unterbrechen willst, aktuell den Thread pausieren. Das wird sicherlich gehen würde ich aber ganz dringend von abraten, denn z.B. wenn gerade die GUI auf den Bildschirm gezeichnet wird und Du dann da "einfach reinhaust" um Deine Daten zu übergeben, kann das unschöne Effekte haben.

Im klassichen OOP Sinn hätte man dafür Events ( http://de.wikipedia.org/wiki/Ereignis_(Programmierung) ). Ich meine das würde sich schon realisieren lassen, denn mit Hilfe von Mex kannst Du eine Matlabfunktion aufrufen. D.h. man würde nachdem alle Threads fertig sind einfach über Mex eine definierte Matlabfunktion aufrufen und dort z.B. die Daten hineinreichen. Ich würde das aber so nicht machen, denn die Problematik ist dass man eben den aktuellen Programmfluss undefiniert unterbricht.

Bluesmaster hat Folgendes geschrieben:

Oder zumindest die Ergebnisse irgendwo ablegen wo Matlab selbständig heran kommt?


Nein das brauchst Du nicht. Die fertigen Daten werden in einer C/C++ Struktur in der Bibliothek zwischen gespeichert, Matlab ist dann die aktive Komponente und frage "sind Daten für mich da", wenn ja, lieferst Du sie einfach an Matlab, d.h. Du musst nicht aktiv die Daten in die Matlabsession übertragen, sondern Matlab holt sie sich über eine Mex Funktion. Mein Tipp wäre halt eben so, dass Du wenn Du einen Datenblock vorbereitet hast, einfach ihn an Deine Bibliothek zur weiteren Berechnung schickst und dann kannst Du ja z.B. schon den nächsten Block bearbeiten. In der Schleife, die die Blöcke vorbereitet fragst Du auch regelmäßig nach, ob schon Daten fertig berechnet wurden, wenn ja holst Du sie direkt. Im optimalen Fall hättest Du dann immer einen Block in der Vorbereitung und einen der aktuell bearbeitet wird. Wenn die Schleife durch ist, musst Du dann halt noch Sorge tragen, dass auch alle Datenblöcke, die bearbeitet werden sollen, wieder in Matlab zurück kommen. Das kann man z.B. mit einem Timer machen z.B.

Code:

    function timerfunction()
         if isThreadFinish()
              getPatchData()
         end
    end

---------------
    createTime(@timefunction)
    for i= 1 : numpatches
          x = preprocess_patch(i);
          StartThread( x );
    end
 


Du würdest eben bevor Du Deine Datenblöcke erzeugst einen Timer erzeugen, der alle x Sekunden fragt, ob Daten da sind. Dann erzeugst Du die Blöcke und schiebst sie an die Bibliothek. Stell Dir das wie eine Warteschlange im Kaufhaus vor. Singlethread würde bedeuten, dass Du nur eine Kasse hast, Multithread mehrere. Jeder Käufer geht an die Kasse, an der gerade ein anderer Kunde fertig geworden ist und ich kann dann aktiv nachfragen, ob die Kasse gerade Kunden bedient. Wenn die Kasse keinen Kunden mehr bedienen muss, dann schließe ich sie.
Der "Logger", den ich Dir per PN geschickt hatte funktioniert genau nach so einem ähnlichen Timerprinzip. Ich erzeuge einen Datensatz und gebe ihn an den Thread und dann interessiert es mich nicht mehr, was damit passiert. Ein anderer Thread schaut regelmäßig nach, ob da Daten für ihn da sind, wenn ja nimmt er sie und bearbeitet sie.

Wie und was man da jetzt konkret machen kann / würde, ist natürlich von dem Problem abhängig. Ich habe hier nur einmal grob einige Ideen beschrieben. Wenn Du sagst "ich muss Multithreading machen", dann wäre die nächste Frage "was willst Du genau damit erreichen" und "wie kann man Deine Daten so aufteilen, dass sie eben sinnvoll durch Threads bearbeitet werden können". Zusätzlich gilt, was geschieht mit den Daten, nachdem sie im Thread berechnet wurden.
Du wirst gerade bei der GUI ein Problem bekommen, das Du wahrscheinlich noch nicht siehst: Nehmen wir an, Du hast die GUI offen und dort bereitest Du nun die Datenblöcke vor und feuerst für jeden Datenblock einen Mex Aufruf, der die Thread erzeugt. Die Threads werkeln nun vor sich hin und Du schließt die GUI. In diesem Fall hast Du das Problem, dass die Threads noch alle schön fertig arbeiten werden, die Daten dann irgendwie zwischen speichern, aber niemand holt sie ab, weil ja die GUI zu ist. Du hast damit Daten irgendwo im Speicher rum liegen. Da Matlab noch aktiv ist, werden diese nicht entfernt. Direkt hier siehst Du auch, warum es nicht sinnvoll ist Matlab zu unterbrechen, wenn Daten fertig sind, denn nehmen wir an Du übergibst die Matlab GUI Handles an die Mex Funktion, die Threads werden erzeugt und wenn dann die Daten fertig sind, wird mit Hilfe der Handles eine GUI Funktion aufgerufen. Was passiert, wenn Du die GUI schließt und wieder öffnest!? Für Dich als User ist es die gleiche GUI, für Deine Bibliothek / Threads aber nicht, denn der Handle hat sich verändert. Somit würden die Thread fertig arbeiten und die Benachrichtigung Deiner GUI läuft ins leere bzw. wenn Du nicht vorher prüfst wirst Du da auch einen Fehler bekommen.

Vom Design her, würde ich sagen, wenn die GUI erzeugt wird, erzeugst Du die Threads. Wenn die GUI dann die Daten erzeugt, dann gibst Du die Daten an eine Warteschlange in der Bibliothek. Die Threads schauen in der Warteschlange nach, ob Daten drin sind, wenn ja nehmen sie einen Datensatz raus und bearbeiten diesen. Wenn sie fertig sind legen sie den Datensatz in eine weitere Warteschlange für die Abholung. Wenn nichts in der Warteschlange drin ist, pausieren die Threads. Die Matlab GUI erzeugt nun die Datenblöcke und gibt diese an die Warteschlange, gleichzeitig kannst eben via Timer oder in einer Schleife bei der Bibliothek nachfragen ob Daten in der Abholung bereit stehen, wenn ja holst Du sie Dir zurück in Matlab (wie oft Du nachschaust ob was da ist, ist abhängig von Deinem Programmfluss). Wenn die GUI nun beendet wird, dann entfernst Du alle Threads, d.h. jeder Thread wird zum nächst möglichen Zeitpunkt terminiert und die beiden Warteschlangen werden geleert.
Damit hast Du die Threaderzeugung nur einmal beim Start der GUI. Zusätzlich ist sicher gestellt, dass keine Daten liegen bleiben, weil beim Beenden der GUI alle Threads terminiert werden. Zusätzlich kannst Du selbst bestimmen, wann Du die Daten abholst. Evtl muss man noch einmal genau schauen, was passiert wenn die GUI "abstürzt", in diesem Fall sollten die Threads ja auch terminiert werden.

Nu als weiterer Gedankengang, falls es Dir dann die Performance nicht ausreicht, kannst Du auch in ähnlicher weise Webservices / Clusterstrukturen an dieser Stelle anbinden, denn Du müsstest dafür eben nur die Threadfunktion anpassen, d.h. sie berechnet die Daten nicht mehr selbst, sondern "schickt" sie irgendwohin, wo sie bearbeitet werden und lässt sich die Rückgabe geben. Aus Matlabsicht, würde man dies dann nicht merken.
Private Nachricht senden Benutzer-Profile anzeigen
 
Bluesmaster
Themenstarter

Forum-Century

Forum-Century



Beiträge: 203
Anmeldedatum: 13.11.11
Wohnort: Gera
Version: 2012a
     Beitrag Verfasst am: 02.08.2012, 17:31     Titel:
  Antworten mit Zitat      
Das ist alles sehr verständlich erklärt und wird hoffentlich auch
funktionieren. Hier hab ich trotz zäher Recherche nichts gefunden:

Zitat:
Daten werden in einer C/C++ Struktur in der Bibliothek zwischen gespeichert


Wie komme ich da ran? Ich habe doch keine Handles von irgendetwas?


Eine extrem zähe Recherche hat nur die andere Richtung ergeben.
Also C > Matlab mittels der sogenannten "engine"

#include "engine.h"
int engPutVariable(Engine *ep, const char *name, const mxArray*pm);



Aber davon hast du ja eher abgeraten. für das "getData(obj)" bräuchte
ich ja irgendeinen Aufhänger der mich in die C++Struktur führt.
(edit: startet auserdem eine eigene Matlabinstanz oder?)


PS: interessante Seite flashpixx.de
30 Programmiersprachen, das ist echt respektabel, falls du mal ein
ingenieurstechnische Problem hast schreib mir einfach eine PN Smile
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.08.2012, 19:14     Titel:
  Antworten mit Zitat      
Bluesmaster hat Folgendes geschrieben:

Zitat:
Daten werden in einer C/C++ Struktur in der Bibliothek zwischen gespeichert


Wie komme ich da ran? Ich habe doch keine Handles von irgendetwas?


Das ist alles im C++ STL vorhanden !
http://www.cplusplus.com/reference/stl/vector/
http://www.cplusplus.com/reference/stl/list/
http://www.cplusplus.com/reference/stl/map/
http://www.cplusplus.com/reference/stl/multimap/
http://www.cplusplus.com/reference/stl/multiset/
http://www.cplusplus.com/reference/stl/priority_queue/
http://www.cplusplus.com/reference/stl/queue/
http://www.cplusplus.com/reference/stl/set/

Dafür benötigt man keine (!) Handles, das ist in C++ vorhanden


Bluesmaster hat Folgendes geschrieben:

Eine extrem zähe Recherche hat nur die andere Richtung ergeben.
Also C > Matlab mittels der sogenannten "engine"

#include "engine.h"
int engPutVariable(Engine *ep, const char *name, const mxArray*pm);


Wie schon geschrieben, würde ich einen Zugriff von C/C++ nach Matlab nicht machen, da es
einige Schwierigkeiten mit bringt.


Bluesmaster hat Folgendes geschrieben:

Aber davon hast du ja eher abgeraten. für das "getData(obj)" bräuchte
ich ja irgendeinen Aufhänger der mich in die C++Struktur führt.


Nein "getData" läuft innerhalb der aktuellen Matlabinstanz (Session), also innerhalb des Matlabsinglethread.
Ich würde das evtl so benennen
Code:

    void mexInit( void ); // erzeugt so viele Threads wie möglich
    void mexRelease( void ); // entfernt alle von init Threads erzeugten Threads
    void mexAddData( MexParameter ); // fügt Daten aus Matlab in die Warteschlange ein
    void mexGetData( MexParameter ); // holt Daten aus der Warteschlange und liefert sie an Matlab
 


Alle 5 Funktionen laufen innerhalb der aktuellen Matlabinstanz und sind blockierend, d.h. sie blockieren den aktuellen Matlabthread
Die init-Funktion erzeugt mit Hilfe der Boostthreads einen Satz an Threads, die dann die Verarbeitung übernehmen. Das init darf nur einmal zu beginn aufgerufen werden. Die Threaderzeugung ist non-block, d.h. der Thread wird erzeugt und dann direkt der nächste. Nachdem der Thread erzeugt wurde greift er auf die Warteschlange zu und arbeitet die Warteschlange ab sofern etwas drin ist. Das release macht das Gegenteil es entfernt alle Thread bzw. stoppt diese vorher.
Mit addData werden dann aus Matlab die Daten passend in eine C/C++ Datenstruktur umgewandelt und eben in der Warteschlange übergeben (die Threads greifen auf die Warteschlange zu), das getData gibt dann einen Datensatz aus der Warteschlange zurück an Matlab und entfernt den Datensatz aus der internen Wartenschlange. addData hat somit eine eigene Warteschlange und getData ebenfalls, die Threads nehmen die Daten aus der einen Warteschlange die Daten raus, bearbeiten und legen in die andere ab.

Parameter, die aus Matlab an C bzw von C an Matlab übergeben werden, werden immer als Parameter übergeben (ähnlich ist auch das Java Native Interface (JNI), um von Java auf C zugreifen zu können). Da C selbst wiederum komplett in C++ enthalten ist, kann man dann die C-Funktionalität auch direkt mit einem C++ Compiler übersetzen und eben die Aufrufe mischenm d.h. Du schreibst C Aufrufe und kannst dann innerhalb dieser C++ Aufrufe (Boost Thread) verwenden. compilierst dann alles mit einem C++ Compiler (Visual Studio / G++) und rufst es von Matlab auf.
Was hier "technisch" wichtig ist, ist folgendes: diese oben beschrieben Funktionen müssen natürlich die Konvertierung von / nach Matlab vornehmen, dazu gibt von Mex spezielle Aufrufe (mxGetScalar usw), d.h. Du musst den Matlabdatentyp in einen C/C++ Typ (int, unsigned int, ggf boost::ublas::matrix, boost::ublas::vector) umwandeln. Das geschieht dann als blocked Struktur, d.h. z.B. das AddData
konvertiert dann eine Matlab-Cell-Array z.B. in einen std::vector, der dann in die Warteschlange (meist als C++ Queue definiert) abgelegt wird.
Die Threads schauen dann in dieser Queue nach, ob etwas drin ist, nehmen sich dann das nächste Element, bearbeiten es und legen es dann in eine "Output-Warteschlange". Das GetData, schaut dann in der "Output-Warteschlange", wenn es aus Matlab aufgerufen wird, nach, ob etwas drin ist, wenn nein, dann liefert es zurück an Matlab z.B. [], wenn etwas drin ist, nimmt es das nächste Element, konvertiert es in die passenden Matlab Daten und entfernt dann dieses Element aus der Warteschlange.
Die Konvertierung kann natürlich theoretisch auch der Thread machen, somit würde add/get nnur das Einfügen bzw. Herausholen aus der Warteschlange machen und somit nur minimal den Matlabthread blockieren. Wichtig ist dabei natürlich, dass sicher gestellt ist, dass das Schreiben und Lesen der Warteschlangen thread-safe ist (STL Strukturen sind i. Allgm. nicht thread-safe !!).

Da ist wirklich kein "Magic" dabei und es ähnelt sehr viel z.B. JNI (http://de.wikipedia.org/wiki/JNI), d.h. evtl wäre es zur Übung erst einmal sinnvoll, dass Du einfach Dir die Beispiele von JNI anschaust und evtl damit das ganze probierst, d.h. Wie bekommt man Daten aus Java nach C und von C nach Java, dann das ganze erweitern nach C++ und als letztes das ganze mit Threads.
Wenn man es vom Konzept her richtig macht, dann läuft das ganze innerhalb des Matlabscops, d.h. das init / release / get- & addData ist immer nur innerhalb des aktuellen Matlabprozesses vorhanden und arbeitet somit immer nur auf den eigenen Daten, d.h. wenn Du zwei Matlabinstanzen laufen hast und in beiden Deine GUI aufmachst, dann sieht jede GUI nur ihre Daten und ihre Threads.
Mein Tipp wäre somit auch im Sinne des Lernes von C/C++, dass Du erst einmal versuchst das addData zu schreiben, dabei ist auf korrektes Speichermanagement zu achten. Als nächstes würde man das getData machen, d.h. das addData legt einfach die Daten nur in eine entsprechende Warteschlange, das getData holt die Daten wieder heraus, also in Matlabcode sieht das dann so aus
Code:

     funciton x = doit( varargin )
             myMexFunction_addData( varargin{1} );
             myMexFunction_doSomething();
             x = myMexFunction_getData();
     end
 


Das doSomething muss dann einfach die Daten aus der einen Warteschlange in die andere packen. Im nächsten Schritt musst du dann das "doSomething" aus Matlab nehmen und in einen Threadaufruf ersetzen also so (wieder aus Matlab)
Code:

     funciton x = doit( varargin )
             myMexFunction_initThreads();
             myMexFunction_addData( varargin{1} );
             
             x = [];
             while (not(isempty(x))
                   x = myMexFunction_getData();
             end
             myMexFunction_releaseThreads();
     end
 


Jetzt siehst Du, dass ich das doSomething intern mit Hilfe von Threads hand haben muss und eine non-blocking Kommunikation verwende, denn ich muss mit Hilfe des "while" so lange warten bis Daten zurück kommen. Intern auf C++ Seite muss dort natürlich noch einige passieren und die Matlab doit Funktion wird natürlich gerade richtig schlechte Performance haben, denn wir würde für jeden Aufruf Threads erzeugen, Daten rüber schrieben, bearbeiten und warten bis sie fertig sind, Daten holen und dann die Threads wieder beenden, aber Du siehst auch, dass man wenn man nun das doit zerlegt, das ganze auflösen kann. Der "Knackpunkt" sind die Warteschlangen, die innerhalb der Bibliothek liegen. Ich würde wirklich ganz einfach beginnen und erst einmal versuchen Daten von Matlab nach C++ zu bekommen und wieder zurück zu liefern:
Code:

    y = myMexFunction_doit( x );
    x == y;
 

In diesem Fall sollte x gleich y sein. im nächsten Schritt das ganze dann wie oben mit add, doSomething und getData. Das ganze dann auch direkt so angelegt, dass das aus 2 Matlabinstanzen läuft ohne dass sie sich gegenseitig in die Quere kommen und sich ggf die Daten weg hauen. Wenn das klappt dann das ganze mit einem Thread aufbauen, so dass erst einmal ein Thread nur arbeitet (man würde in dem init dann eben nur einen Thread erzeugen). Wenn das klappt dann das ganze mit mehreren Threads und mehreren Matlabinstanzen laufen lassen.

Mein Tipp ist, das ganze in kleine überschaubare Schritte zerlegen und sich Schritt für Schritt an das Problem heran arbeiten und erst den nächsten Schritt machen, wenn der vorherige sicher funktioniert. Evtl das ganze auch unabhängig von Matlab mit Hilfe von JNI ausprobieren, denn das Prinzip ist das gleiche. Noch ein Hinweis, falls es notwendig sein sollte, dass Du innerhalb des Threads auf Matlabroutinen (wie z.B. eig) zurück greifen musst, ist dies auch möglich entweder darüber, dass Du direkt die Matlabfunktion aufrufst, wobei Du dann natürlich wieder passend die Daten hin- und her konvertierne musst, oder aber Du kannst z.B. alle direkt mit Hilfe der Boost Numeric Bindings direkt die Daten aus den Boost Vektor- / Matrixstrukturen an die LAPack übergeben. Mein praktischer Ratschlag ist, dass Du eine Bibliothek in C++ schreibst, die eben jeden Datenblock völlig unabhängig von Matlab verarbeitet. Um diese Bibliothek (wenn sie fertig ist), einen Mex-Wrapper baust, der eben nur die Daten von Matlab entgegen nimmt und passend für die Bibliothek verarbeitet und die von der Bibliothek erzeugten Daten wieder zurück an Matlab liefern kann. Ich würde innerhalb des init-Aufrufes dann ein C++-Singleton Objekt erzeugen ( http://de.wikipedia.org/wiki/Singleton ), das die Threads und Warteschlangen erzeugt. die add/get-Aufrufe werden dann einfach an das Singleton-Objekt durch geschliffen und das release entfernt das Singleton-Objekt wieder. Damit bleibt alles innerhalb eines Objektes und Du musst dann lediglich dafür Sorge tragen, dass dann jede Matlabinstanz ein eindeutiges Singletonobjekt bekommt.
Private Nachricht senden Benutzer-Profile anzeigen
 
Bluesmaster
Themenstarter

Forum-Century

Forum-Century



Beiträge: 203
Anmeldedatum: 13.11.11
Wohnort: Gera
Version: 2012a
     Beitrag Verfasst am: 02.08.2012, 19:57     Titel:
  Antworten mit Zitat      
für das ganze Know How hätte ich vermutlich wochen recherchiert.


Ich werde mich mal reinarbeiten und dann den Fortschritt berichten


vielen Dank schon einmal


Gruß

Blues
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.08.2012, 14:20     Titel:
  Antworten mit Zitat      
Ich habe aufgrund dieser Diskussion einmal ein Mex C++ Beispiel eines Loggers entwickelt und beschrieben: http://flashpixx.de/2012/08/matlab-mex-beispiel/

Ich setze hierzu die Boost Bibliotheken ein, die ein C++ Singleton-Pattern implementieren, das Nachrichten über die STL Strukturen thread-safe in eine Datei schreibt (cross-plattform). Das ganze wird dann mit Hilfe von Mex in Matlab eingebunden.
Hoffe es hilft jemanden weiter und für Korrekturen bin ich dankbar
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 04.08.2012, 17:34     Titel:
  Antworten mit Zitat      
Hallo,

in Antwort auf die originale Frage:
Wenn batch in dieser Form verwendet wird, wird eine (1) neue MATLAB-Sitzung gestartet und der Code dort ausgeführt. Das ist wenig sinnvoll, da die Ausführungszeit genauso groß wie vorhin ist, vorher aber eben noch die MATLAB-Sitzung gestartet werden muss.

Für das Parallelisieren innerhalb mit der Parallel Computing Toolbox würde ich zunächst matlabpool / parfor empfehlen. Diese Befehle sind in der Anwendung recht einfach, und wenn der MATLAB Pool einmal gestartet ist, ist der Overhead relativ gering.

Ebenso wie bei der Parallelisierung außerhalb von MATLAB ist es bei der Arbeit mit der Parallel Computing Toolbox entscheidend, dass sinnvoll parallelisiert wird. Was sinnvoll ist, muss von Anwendung zu Anwendung entschieden werden.

Die Vorschläge von flashpixx mögen für eine etwas bessere Performance sorgen; ich würde jedoch offen gesagt den auf den ersten Blick meines Erachtens sehr beträchtlichen Aufwand scheuen.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
flashpixx
Forum-Guru

Forum-Guru


Beiträge: 355
Anmeldedatum: 19.04.08
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 04.08.2012, 18:55     Titel:
  Antworten mit Zitat      
Harald hat Folgendes geschrieben:

Für das Parallelisieren innerhalb mit der Parallel Computing Toolbox würde ich zunächst matlabpool / parfor empfehlen. Diese Befehle sind in der Anwendung recht einfach, und wenn der MATLAB Pool einmal gestartet ist, ist der Overhead relativ gering.


Soweit ich das gesehen habe, macht die Toolbox "im Kern" auch nichts anderes. Sie stellt letztendlich einen Threadpool zur Verfügung und verteilt dann via Queues die Daten auf die Threads, wobei bei der Toolbox natürlich noch die Skalierbarkeit auf mehrere Nodes möglich ist.

Harald hat Folgendes geschrieben:

Ebenso wie bei der Parallelisierung außerhalb von MATLAB ist es bei der Arbeit mit der Parallel Computing Toolbox entscheidend, dass sinnvoll parallelisiert wird. Was sinnvoll ist, muss von Anwendung zu Anwendung entschieden werden.


Das hatte ich ja auch schon geschrieben, dass man einfach Parallelisierung des Parallelisierungswillens nicht bessere Performance bringt, teilweise sogar schlechter wird.

Harald hat Folgendes geschrieben:

Die Vorschläge von flashpixx mögen für eine etwas bessere Performance sorgen; ich würde jedoch offen gesagt den auf den ersten Blick meines Erachtens sehr beträchtlichen Aufwand scheuen.


Wenn es hier um eine reine Threadimplementierung gehen sollte, dann ist der Aufwand gering. Letztendlich würde man aus der STL 2 Queues erzeugen und thread-safe als Singletonpattern beschreiben (d.h. eine Klasse), dazu dann eine "Workerklasse", die dann eben eben n-fach anhand der durch die Hardware festgelegte Threadanzahl startet. Die Threadroutine ist letztendlich ja auch nur eine Funktion. Entsprechenden Lockmechanismus auf die Queues setzen, was mit Boost Thread einfach ist, da der Lock automatisch gelöst wird, sobald die Lockvariable out-of-scope geht. Abschließend wäre nur noch der Mex Wrapper zu schreiben, was aber letztendlich einfach ist, denn der Mex Wrapper muss nur die Singleton Instanzen erzeugen / releasen und eben n Working Objekte erzeugen.

Dahinter liegt letztendlich http://en.wikipedia.org/wiki/Thread_pool_pattern

Da der OP ja hier eine Parallelisierung via Threads wünschst, gehe ich davon aus, dass er sich der Problematik bewusst ist. Der Vorteil der Mex Variante in meinen Auge wäre, dass man nachdem der Mex Code einmal geladen ist, keinen weiteren Overhead mehr hat, d.h. die Singleton Instanz wird ein einziges mal erzeugt und bleibt erhalten und es kann somit wirklich im Hintergrund zu Matlab arbeiten. Sind Daten da, arbeiten die Threads, sind keine da pausiert man sie.
Private Nachricht senden Benutzer-Profile anzeigen
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 04.08.2012, 19:16     Titel:
  Antworten mit Zitat      
Hallo flashpixx,

ich habe mich bewusst nur auf die ursprüngliche Frage bezogen und nicht den ganzen Thread gelesen.

Wenn ich mir ansehe, was du in deinem Beitrag von 2.8., 19:14 alles geschrieben hast, dann würde ich den Aufwand nicht als "gering" bezeichnen. Vor allem nicht, wenn man das mit matlabpool / parfor vergleicht.

Grüße,
Harald
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen

Gehe zu Seite 1, 2  Weiter

Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.