Seite 1 von 2

Qt Threads aus verschiedene Core verteilen

Verfasst: 31. Juli 2009 09:47
von RavenIV
Hallo 'Gemeinde

Ich habe eine Anwendung, die auf 5 Threads verteilt ist.
Ein GUI-Thread und 4 Worker.
Programmiert ist das in Python (GUI) und C++ (Worker).

Dazu haben wir einen PC mit einem Multicore-Prozessor unter WinXP-SP3.

Nun habe ich aber festgestellt, dass ein Core fast glüht und die anderen drei Cores sich langweilen.

Wie kann ich es schaffen, dass die vier Worker-Threads auf die vier Cores verteilt werden?

Quellcode darf ich leider keinen Posten wegen Geheimhaltung. :-(

Danke

Verfasst: 31. Juli 2009 11:16
von RHBaum
erst mal sicherstellen, das auch alle 4 threads gleichmaessig arbeiten, und nicht einer rackert und die restlichen 3 auf den einen warten ....
Kannst du das zu 100% ausschliessen, gibts weitere optionen.

es gibt winapi funktionen, mit denen man mehr kontrolle ueber die threads hat. Notfalls im c++ teil auf die qt verzichten und c++ winapi programmieren.

mit paar schmutzigen hacks kommst auch auf die threadID von den QThreads und kannst ueber die winapi da bissi was steuern.

Nachteil: du verlierst die plattformunabhaengigkeit oder musst die selber einprogrammieren.

weiterhin.... wie komplex ist die synchronisation zwischen den einzelnen threads und wie extensiv der datenaustausch.
Iss das ziemlich trivial, dann wuerd ich statt multithreading eh auf multiprozessing ausweichen, damit kommen die meisten BS auch besser klar (besonders unixe). windows verteilt die prozesse viel besser auf unterschiedliche kerne als bei threads ....
(andere berichten anders, aber bei uns hier auf mehreren rechnern mit DualCores / quadcores, windows XP SP2, qt 4.5 momentan, visual studio 2005, kein mp support, legt er alle threads von einem prozess immer standardmaessig auf einen Kern. erst wenn ich manuell eingreife, bekomm ich beide kerne ausgelastet. und nein ich mein ned den compiliervorgang, da verwendet er eh immer nur 1 kern, sondern wirklich das ausfuehren des programms)

Ciao ...

Verfasst: 31. Juli 2009 11:55
von DarkWotan
RHBaum hat geschrieben:und nein ich mein ned den compiliervorgang, da verwendet er eh immer nur 1 kern
Hat zwar nichts mit dem Thema zu tun, aber das muss ich jetzt los werden:
Probier mal den Schalter /MP bei den Compilereinstellungen ;-)

Verfasst: 31. Juli 2009 13:31
von RavenIV
Die vier Worker machen alle das selbe, jedoch mit unterschiedlichen Kameras. Wir haben also vier identische Kameras und die Worker untersuchen die Bilder der Kameras.
Kommunikation der Threads besteht nicht.
Die Threads werden gestartet, arbeiten eine gewisse Zeit, geben ein Ergebnis zurück und beenden sich.

Plattformunabhängigkeit ist wichtig, weil die nächste Version der Software unter Linux laufen soll.

Gibt es Tips, Ideen, wie wir die SW von mehreren Threads zu mehreren Prozessen umbauen können?

Verfasst: 31. Juli 2009 15:14
von solarix
Spannend.. weil mich das auch interessierte, habe ich mal was gebastelt. ergebnis:

1. 2 QThreads arbeiten (auf meinem Ubuntu, Qt 4.4.3) in _einem_ Core.
2. 2 QRunnables in einem QThreadPool arbeiten auf _zwei_ Cores.

Da hättest du die Lösung ;)

Verfasst: 31. Juli 2009 15:33
von Christian81
@solarix: Deine erste Aussage kann ich nicht wirklich nachvollziehen - wenn es wirklich so ist liegt es aber sicherlich nicht an Qt sondern an irgendwelchen OS-spezifischen Dingen / Einstellungen.

@RavenIV: Bist Du wirklich sicher das deine Verarbeitungen auch in den Threads passieren und nicht im MainThread? Sowas geht schnell wenn man nicht korrekt programmiert. Schau Dir lieber mal mit QThread::threadId() an in welchen Thread genau die Abarbeitung abläuft.

Verfasst: 31. Juli 2009 15:37
von RavenIV
Ja, ich bin sicher.
In der Logdatei sieht man, dass abwechselnd Einträge von "Worker1" bis "Worker4" kommen.

Wo und wie kann ich überprüfen, ob die Threads auch richtig gestartet werden?
Ich habe Teile der Software von einem Kollegen (der nicht mehr da ist) übernommen.

Verfasst: 31. Juli 2009 15:56
von solarix
@Christian81: Ich war selbst überrascht. Zwei QThreads mit einem "while (1);" ergeben bei meinem (Default-Ubuntu Intrepid/Linux 2.6.27-11) nur Halblast. In einem ThreadPool Volllast. "top" lässt da kein Zweifel.. Allerdings bin ich deiner Meinung: das muss OS-spezifisch sein. Ich wollte das nur erwähnen, weil Raven ja Linux als Zielsystem hat..

@RavenIV: "Wo und wie kann ich überprüfen, ob die Threads auch richtig gestartet werden?" Ein Mini-Benchmark kannst du doch in etwa 20s selbst erstellen... einfach 4 Threads mit "while (1);" starten.. wenn dann der Rechner Volllast hat, ist dein Programm faul.

Verfasst: 31. Juli 2009 16:01
von Christian81
RavenIV hat geschrieben:Ja, ich bin sicher.
In der Logdatei sieht man, dass abwechselnd Einträge von "Worker1" bis "Worker4" kommen.
Nur weil alle 4 Objekte was ausgeben heißt es nicht dass dies auch in 4 verschiedenen Threads passiert... :roll:

@Solarix:

Code: Alles auswählen

#include <QCoreApplication>
#include <QThread>

class MyThread : public QThread
{
  public:
    MyThread() {}
    ~MyThread() {}
    
    virtual void run()
    {
        while(1) {
          // do nothing
        }
    }
};

int main(int argc, char**argv)
{
  QCoreApplication app(argc, argv);
  
  MyThread t1;
  MyThread t2;
  t1.start();
  t2.start();
  
  return app.exec();
}
'top' zeigt mir 195% CPU-Last bei 2 Cores - Vollast würde ich sagen.

Verfasst: 31. Juli 2009 16:24
von Ryu1991
Wenn die Threads eh unabhängig sind.
Warum machst du dann nicht 4 Einzelne Programme draus. Dann kannst du (zumindest unter Windows) jedem Programm einen Kern zuweisen.
Und das Bild-Signal (Ich geh mal davon aus, weil du Kameras erwähntest) kannst du ja per Shared-Memory oder so an deine GUI weiterleiten.

EDIT: Habe gerade gesehen, dass deine GUI und die QT Units nicht das selbe Programm sind, also isses ja noch einfacher, und du müsstest statt einem Signal halt 4 annehmen.

Verfasst: 31. Juli 2009 16:33
von solarix
@Christian81: Genau das gleiche ergibt bei mir 100% (=Halblast, 50% Idle-Time). Spannend, was fuer eine Linux-Version hast du?

Verfasst: 31. Juli 2009 19:29
von Christian81
@Solarix: bin openSUSE-Fan :wink:

Verfasst: 3. August 2009 09:27
von RavenIV
Um ein paar Vermutungen / Unklarheiten zu beseitigen:

- Zielplattform ist (noch) WinXP, Linux kommt wohl erst Ende Jahr.
- GUI und die Worker laufen in einer gemeinsamen Executable.
- Die Worker hängen eng mit der GUI zusammen, sie werden von der GUI gestartet, bekommen Arbeit zugewiesen, melden der GUI das Ergebnis und beenden sich anschliessend. Beim nächsten zu untersuchenden Werkstück beginnt das Spiel von vorne.
- das Logging kommt definitiv von den 4 Threads, weil jeder Thread eine eigene ID hat für das Log.
- Abhängigkeiten der Worker untereinander gibt es nicht.

Werde mal mit nem Mini-Programm das System testen.

Danke schon mal.
Weitere Ideen / Vorschläge nehme ich gerne an.

Verfasst: 4. August 2009 14:18
von RavenIV
Ich habe jetzt ein kleines Mini-Programm erstellt.
Es beinhaltet im Groben den Code von Christian81 plus eine kleine GUI drum herum, damit man die Anzahl Threads einstellen kann.

Bei einem "normalen" Intel Core 2 Q6600 Quad-Core sieht man nicht das erwartete Ergebnis, dass einzelne Cores mit 100 % laufen und der Rest mit 0 %, sondern es werden immer alle Cores in die Ausführung einbezogen.
Nur beim Intel Core i7 sieht man, dass wirklich jeder Thread auf einem Core ausgeführt wird.

Code habe ich angehängt.

Verfasst: 4. August 2009 16:03
von Christian81

Code: Alles auswählen

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
22355 ehrliche  20   0  237m  19m  14m S  195  1.0   0:30.81 Threadtest
-> 195%CPU - Last bei 2 Threads. Also wie gewünscht.
Kauf Dir ein ordentliches OS - das liegt definitiv nicht an Qt :)