Prozessorbelastung auslesen und graphisch darstellen



  • Kann ich machen. Also prinzipiell ist mir die ganze Nummer mit C/C++ und MatLab ja klar. Zu mindest wenn man ein Mex-File schreiben will, dass dann von MatLab über die mexFunction(...) aufgerufen werden soll.
    Nur die Nummer mit der graphischen Oberfläche von Borland ist mir jetzt nicht ganz klar.

    Tja, für das Multithreading kannst du entweder die Borland-Klasse TThread (keine Ahnung, wie die funktioniert. Hab sie noch nie verwendet.) benutzen oder du schaust dir die Winapi mit CreateThread und Konsorten an, welche ich nun wieder rum verwende oder auch verwendet habe um Multithreading unter Matlab möglich zu machen.



  • Hierfür sollte ein Standard-TThread völlig ausreichend sein. Hier gibt es auch irgendwo ein Tutorial zu TThread, ich bin nur zu faul den Link zu suchen. 😉

    Schau Dir das Tutorial an... Bei Problemem helfen wir gerne weiter.

    Grüße Joe_M.



  • Hallo Joe_M,

    da nehm ich dich dann aber beim Wort. Bin mir sicher, dass ich auch nach dem Durchlesen der Tutorials und der Hilfe meine Schwierigkeiten haben werde.
    Und dann aber bitte keine Verweise mehr auf Sachen zum Lesen. 🙄

    Okay, wie fügt man Matlab Code in ein C-Projekt ein.
    Beispiel am BCB6:

    1. Schritt: Schreiben des m-Files unter Matlab, z.B.
    
                function y = foo(x)
                y = 2*x;
    
    2. Schritt: Kompilieren des m-Files aus Auslagern des Codes in eine C-Shared 
                Library; Auf der Kommandozeile:
    
                >> mcc -W lib:foo -T link:lib foo.m
    
       Jetzt entsteht: foo.h, foo.c, foo.ctf, foo.dll
       foo.h und foo.dll müssen später ins BCB Projekt inkludiert werden und 
       foo.ctf muss später im Anwenderverzeichnis liegen!
    
    3. Schritt: Das BCB Projekt
    
       Um die .dll ansprechen und ausführen zu können, muss auf dem späteren System
       unbedingt eine Matlab Component Runtime installiert sein, sowie das ctf 
       Archiv im Anwenderverzeichnis vorhanden sein. Die MCR wird standardmäßig zu 
       jeder Matlab Version mit Compiler Toolbox mitgeliefert und kann weitergeben
       werden.
    
       Außerdem müssen die Verzeichnisse <matlabroot>extern\include 
       sowie                             <matlabroot>extern\lib\win32\borland
       mit unter den Projektoptionen eingebunden werden!
    
       Alle Ein- und Ausgabeparameter, ganz egal welchen Typs sie sind(Double, int,
       CellArray, StructArray etc.) haben in C den mxArray Typ.
    
    Zu BCB
    
    include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "foo.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    void display(const mxArray* in);
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     //Aufruf der MCR
       mclInitializeApplication(NULL,0); 
    
     //Deklaration der Ein- und Ausgabeparameter
       mxArray *in1;
       mxArray *y = NULL;
    
     //Beispieldaten zur Eingabe   
     double data[] = {1,2,3,4,5,6,7,8,9,10};
    
     //Anlegen eines Spaltenvektors mit Doublewerten der Dim (10,1)
     in1 = mxCreateDoubleMatrix(10,1,mxREAL);
     memcpy(mxGetPr(in1), data, 10*sizeof(double));
    
     //Laden der .dll
     if (!fooInitialize())
     {
      ShowMessage("Fehler beim Laden der dll");
      return;
     }       
    
     //Aufruf der Funktion mlfFoo und Übergabe Ein- und Ausgabeparameter
     mlfFoo(1, &y, 1, &in1);
    
     //Zugriff auf den Rückgabewert
     display(y);
    
     //Destroy Array, Speicher freigeben
     mxDestroyArray(y); y=0;
     mxDestroyArray(in1); in1=0;
    
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
    {
     //Terminiere die .dll und MCR
     fooTerminate();
     mclTerminateApplication();   
    
    }
    //---------------------------------------------------------------------------
    void display(const mxArray* in)
    {
        int i=0;
        int r=0; 
    
        //Zeiger auf das mxArray (Rückgabewert)
        double *data; 
    
        //mxGetM = Anzahl der Zeilen im Rückgabewert
        r = mxGetM(in);
    
        //Zeiger auf den Vektor
        data = mxGetPr(in);
    
        //Ausgabe der Daten 
        for( i = 0; i < c; i++ )
        Form1->StringGrid1->Cells[0][i]=data[i];
    
    }
    

    Das wars eigentlich schon. Die eigentliche Berechnung erledigt dann die MCR.
    Mann muss sich nur noch um die korrekte Deklaration der Ein- und Ausgabewerte kümmern und um die korrekte Übergabe etc.

    Das ganze funktioniert in gleicherweise mit Strukturen, Cell-Arrays, Matrizen etc...

    Und für genau so eine Berechnung bräuchte ich einen zweiten Thread.
    Beginn vor dem Aufruf der Funktion mlfFoo, da er dann in die .dll geht und auf den Rückgabewert wartet.

    Hoffe ich konnte die ganze Thematik einigermaßen verständlich erklären.

    Liebe Grüße und schönes WE
    Todd



  • Aha, gut auf dem Weg hab ich mit Matlab noch nie gearbeitet. Ich denke mal, das ist sinnvoll, wenn man Simulationsberechnungen oder komplexere mathematischen Berechnungen machen will. Da Matlab solche Sachen ja schon implementiert hat, brauch man sich dann nicht die Arbeit machen und alles selbst schreiben.

    Dann hier mal der WinApi-Weg:

    DWORD stelleBerechnungAn(LPVOID ThrParam); //Aussehen einer startfähigen Funktion
    
    //zum Starten dann selber, braucht man
    
    HANDLE hThr = NULL;
    DWORD ThrId = 0;
    
    hThr = ::CreateThread(NULL, 0, stelleBerechnungAn, NULL, 0, &ThrId);
    if (hThr == INVALID_HANDLE_VALUE)                 // ^
    { /*Fehlerbehandlung*/ }                          // |
                                //falls Parameter in die Funktion sollen, dort
                                //den Zeiger übergeben
    

    Eleganter wäre es allerdings die Funktion als Member einer Klasse zu implementieren und die Klasse dann selbst als Parameter zu übergeben.
    Wichtig ist dann nur das stelleBerechnungAn(...) static ist.

    Na vielleicht hilft's dir ja. Wenn du die TThread-Klasse nimmst, musst du dich dann wohl an die anderen halten. 😃



  • Hallo,

    ich hab mich jetzt mal dazu entschlossen die WinAPI zu benutzen.
    Scheint mir irgendwie besser zu gefallen.

    //---------------------------------------------------------------------------
    
    #include <vcl.h>
    #pragma hdrstop
    
    #include "Unit1.h"
    #include "windows.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
            : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    DWORD WINAPI MyThread( LPVOID lpParam ) 
    {
     for (int i=1;i<100000;i++)
     Memo1->Lines->Add("Neuer Thread");
    }
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
     LPDWORD dwThreadId;
     CreateThread(NULL, 0, MyThread, NULL, 0, NULL);
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button2Click(TObject *Sender)
    {
     ShowMessage("HauptThread");        
    }
    //---------------------------------------------------------------------------
    

    Ist das jetzt schon mal so okay? Es funktioniert jedenfalls. Kann Button2 betätigen, während die Eintragung in das Memofeld noch stattfindet.

    Also ist jetzt erstmal ein kleiner Ansatz, bin aber schonmal begeistert, dass es bis jetzt zumindest funktioniert. 😮

    Zum Thema Matlab Code:

    Es eignet sich hervorragend zur mathematischen Berechnungen und in Folge dessen auch zur Programmierung. Für welche, die wie ich Matlab schon seit Jahren nutzen ist es zehnmal leichter damit umzugehen als eine Programmierung in C++ zu starten.

    Deshalb nutze ich die Schnittstelle zwischen C und Matlab. Die Programmierung im BCB hat für mich nur den Sinn, eine schöne, bedienerfreundliche und unabhängige Software zu entwickeln.

    Danke schonmal für eure Hinweise und liebe Grüße
    Todd



  • Hmm, also das sieht sehr einfach gehalten aus. Du solltest wenigstens eine Fehlerabfrage nach der Erstellung einbauen. Kann ja sein, dass irgendwas bei der Erstellung schief geht und so merkst du's nicht mal.
    Ausserdem ist es auch sinnvoll sich ein Handle von dem Thread zu holen, so dass du beim Schliessen deiner Anwendung den Thread über TerminateThread(...) abschiessen kannst. Allerdings sollte das wirklich nur der letzte Ausweg sein.

    Ich muss dir dringend davon abraten, so unsauber einen Thread zu implementieren, da du so völlig die Kontrolle über den Thread aufgibst. Aber ich geh mal davon aus, dass das jetzt nur Beispielcode ist und du nachher in deinem Programm etwas sauberer arbeiten wirst. 😉



  • Ja klar,

    das war jetzt erstmal ein erster Versuch.
    Das da noch Fehlerabfragen etc. eingebaut müssen, ist mir bewusst.

    Aber der prinzipielle Aufbau ist richtig oder?
    Terminiert sich der neue Thread automatisch nach der Bearbeitung oder muss man zwingend den zweiten Thread schließen, nach dem er abgearbeitet ist?

    Liebe Grüße
    Todd



  • Also so bald die Funktion verlassen wird, ist der Thread auch beendet. Doch es kann ja sein, dass die MCR abstürzt, sich verklemmt etc. Und schon steckt der Thread fest. Deswegen kann es sein, dass du den Thread dann mit Gewalt beenden musst.



  • Okay danke, dann weiß ich bescheid.

    Liebe Grüße
    Todd



  • Fragen zu WinAPI-Threads dann bitte im WinAPI-Forum stellen... 😉

    Aber der prinzipielle Aufbau ist nicht richtig:
    Du greifst aus dem Thread heraus auf Komponenten in Form1 zu. Form1 läuft allerdings im Kontext des Answendungs-Threads. Hier mußt Du zwingend eine Absicherung schaffen, damit nicht beide Threads gleichzeitig auf Memo1 zugreifen können, sondern immer nur einer nach dem anderen (zB mittels einer CriticalSection).
    Wenn Du TThread verwenden würdest, könntest Du dessen Synchronize-Methode verwenden und müßtest Dich nicht selbst um den Zugriffsschutz kümmern.



  • Hallo,

    meine Frage hat sich während den Diskussionen wohl ein wenig von seiner Ausgangssituation weg bewegt. Wenn ich wieder Fragen zur WinAPI habe, dann im WinAPI Forum.

    Jetzt aber nochmal zurückzukommen:

    Das mit dem Memo war nur ein Beispiel. Verstehe aber was du meinst.

    Aber was ist mit folgenden Szenario (versuche nämlich alles um die primitive Methode, die ich wenigstens auf Anhieb verstanden habe zu retten):

    Im zweiten Thread wird nur die .dll aufgerufen.
    In der Zwischenzeit, werden alle relevanten Objekte auf der Oberfläche deaktiviert.
    Es ist dem Nutzer also nicht möglich weitere Eingaben zu machen, geschweige denn einen neuen Thread zu starten bzw. auf die .dll zuzugreifen.

    Der Nutzer wird ständig über den Fortschritt der Berechnungen informiert.
    Nach dem die .dll durchgelaufen ist, wird ein Rückgabewert zurückgegeben.
    Dieser Rückgabewert wird dem Hauptprogramm und daher dem Haupt-Thread übergeben. Der zweite zusätzliche Thread ist jetzt geschlossen.
    Die Ergebnisse werden in einem RichEdit ausgegeben und alles ist in Ordnung, oder?

    MfG
    Todd



  • Todd schrieb:

    Es ist dem Nutzer also nicht möglich weitere Eingaben zu machen, geschweige denn einen neuen Thread zu starten bzw. auf die .dll zuzugreifen.

    Der Nutzer wird ständig über den Fortschritt der Berechnungen informiert.
    Nach dem die .dll durchgelaufen ist, wird ein Rückgabewert zurückgegeben.
    Dieser Rückgabewert wird dem Hauptprogramm und daher dem Haupt-Thread übergeben. Der zweite zusätzliche Thread ist jetzt geschlossen.
    Die Ergebnisse werden in einem RichEdit ausgegeben und alles ist in Ordnung, oder?

    Nein, denn auch wenn Du dem User keine Aktonen gestattest, kann es zu konkurienden Zugriffen kommen. Dazu reicht schon völlig aus, das Formular zu verschieben. Dabei kann es schon geschehen, dass der Hauptthread auf das RichEdit zugreift, während Du es aus dem Arbeitsthread gerade befüllst -> bestenfalls eine Fehlermeldung a la 'auf dem Canvas kann nicht gezeichnet werden', schlimmstenfalls ein kompletter Absturz.
    Bei allen Zugriffen auf irgendetwas, das nicht im Kontext des Threads erzeugt wurde, MUSST Du eine Absicherung schaffen. Bei einem RichEdit ist das praktisch schon so gut wie unmöglich.



  • Danke für deine Hilfe.

    Dann doch den TThread von Borland benutzen....
    Heieiei
    Ich werde mir nochmal das Beispiel von Borland ansehen und versuchen dort durchzusteigen.

    Falls ich es dann immernoch nicht kapiert hab, melde ich mich wieder.

    Liebe Grüße
    Todd



  • Mach das... Sieht auf den ersten Blick schlimmer aus, als es ist.

    Versuch einfach nur mal die DLL aus einem Thread heraus anzusteuern. Die Statusinformationen und den Rückgabewert kannst Du erst Mal aussen vor lassen. Du kannst mich dann gerne fragen, wie Du die notwendigen Parameter in den Thread bekommst und den Rückgabewert zurück in das Formular.

    Grüße Joe

    PS Morgen habe ich allerdings eine Schulung, werde also, wenn überhaupt, erst spät abends wieder hier reinsehen...



  • Danke für dein Angebot.

    Sei mir aber auch nicht böse, wenn ich es bis zum Wochenende nicht schaffe.
    Bin bis zu den Ohren in Arbeit versunken.

    Melde mich am WE und entweder überrasche ich euch dann alle mit meinem Wissen oder warte geduldig auf fundierte Hilfe. 🙄

    Liebe Grüße
    Todd

    P.S.: Ich mache dann lieber einen neuen Forumsthread auf, da der Titel hier ja nicht zutreffend ist...


Anmelden zum Antworten