Wie spart man richtig Rechenzeit mit Threads?
-
Skym0sh0 schrieb:
Soweit ich das einschätzen kann, benutzt du zwar Threads, aber lässt diese durch den Mutex sequentiell starten und arbeiten.
Deine "teure" Berechnung ist soweit ich das sehe im Prinzip nur die Addition deiner struct Member. Und das lohnt sich nicht zu parallelisieren, wie du wissen solltest.
Kurzum, du lockst ein Mutex, dann erzeugst du einen Thread, quasi gleichzeitig danach willst du einen weiteren Thread spawnen, was aber wegen dem gelockten Mutex nicht geht, dieses unlockst du im ersten Thread jedoch irgendwann wieder um danach dort Daten zu berechnen.
Dieses Programm macht in der Form keinen Sinn.
Was ist dein eigentliches Ziel? Was hast du wirklich vor?
Edit:
Zu deiner Frage wie man Speed hinbekommt:
- Habe eine entsprechend großes Problem, wo sich Parallelität auch lohnt
- Minimiere oder eliminiere die Synchronisation
- Minimiere oder eliminiere die sequentiellen Programmanteiletntnet schrieb:
Erst mal ist das C und nicht C++. Dann solltest Du nicht einen Mutex in einem anderen Thread frei geben, als in dem, in dem er gelockt wurde. Und immer schön die Fehlercodes abfragen.
Und nun zu Deiner eigentlichen Frage:
Dein Ablauf ist wie folgt:
* Sperre Mutex
* Starte Thread
* Der Thread arbeitet
* Solange der Thread arbeitet, wartet der Hauptthread auf den Thread
* Wenn der Thread seine arbeit verrichtet hat, gibt er den Lock frei und beendet sich
* Der Hauptthread bekommt den Lock und kann den nächsten Thread startenDas Bedeutet, dass die 10 Threads nicht parallel sondern nacheinander laufen. Das spart natürlich gar keine Zeit.
Gast3 schrieb:
Beschreibe was deine wirkliche Datenmenge/Algorithmus ist - dann können wir dir helfen das zu optimieren, mit Threads wenn es geht/sinnvoll ist, oder auch ganz anders
Bedenke:
-triviale Berechnungen in Threads auslagern lohnt sich gar nicht nicht
-deine Daten/Algorithmus muss zerlegt/partitionierbar sein damit deine Threads unabhängig arbeiten können
-zu kleine Happen von Threads berechnen zu lassen lohnt sich auch nichtErstmal Danke für eure Hilfe.
Ich habe keine Ahnung, ob ihr mir nicht vielleicht schon den richtigen Tip gegeben habt und ich habe noch kein volles Programm, in das die Threads eingebaut werden könnten. Aber ich kann vielleicht das Problem besser formulieren.Das hier ist ein sehr sehr ähnliches Programm, in dem die Threads spürbar die Ausführung beschleunigen. Da ist auch kein lock drin.
#include <stdio.h> #include <string.h> #include <pthread.h> #include <stdlib.h> typedef struct{ int a; int b; int result; } args; pthread_mutex_t lock; void* some_func (void *arg) { args argsa = *(args*)arg; for(int j=0;j<10000000;j++); // pthread_mutex_unlock(&lock); argsa.result=argsa.a+argsa.b; printf ("Thread %i result: %i\n", argsa.a, argsa.result); } int main() { pthread_t thread[10]; args ss[10]; int i, index=0; ss[index].b = 1; // pthread_mutex_init(&lock, NULL); clock_t begin, end; double time_spent; begin = clock(); for (index = 0; index < 10 ; index++) { // pthread_mutex_lock(&lock); ss[index].a = index; ss[index].b=1; // printf("index=%d, ", ss.a); pthread_create (thread+index, NULL, some_func, (void*)&ss[index] ); } end = clock(); time_spent = (double)(end - begin); // printf("time: %E\n", time_spent); for(int j=0;j<10000000;j++); for(i=0;i<10;i++) pthread_join ( thread[i], NULL); return 0; }Was mich stört ist Zeile 40. Die Zahl muss zehnmal kopiert werden, einmal für jeden Thread. Wäre das nun eine große Datenmenge, würde das Zeit rauben. Kann man das besser machen?
Wie gesagt, ich hatte noch keine Möglichkeit, gut über eure bisherigen Antworten nachzudenken. Vielleicht habt ihr mir die Antwort schon gegeben und ich versteh sie noch nicht.
Darf gern ins C-Forum kopiert werden.
-
Das ist doch derselbe Code nur dass die Locks auskommentiert sind. Und ganz klar ist dann auch, dass der Code schneller läuft. Weil es echt parallel ist und nicht wie bei deinem gelockten Beispiel sequentiell.
Zu deiner Anmerkung mit den Daten kopieren:
Ja, es kommt drauf an was für ein Problem du berechnest. Wenn in jedem Schritt alle Threads/Prozesse untereinander Kilo-/Mega-/Giga-byteweise Datenaustauschen müssen, dann wird das schlecht anders gehen. Wenn es aber nur (d)eine Implementierungsungenauigkeit ist, dann könnte man da auch drum herum kommen.Aber das kommt auf das Problem an.
-
Beschreibe was deine wirkliche Datenmenge/Algorithmus ist - dann können wir dir helfen das zu optimieren, mit Threads wenn es geht/sinnvoll ist, oder auch ganz anders
bitte nicht wieder deinen Quelltext posten - das ist keine Beschreibung und es ist auch einfach ein schlechtes Beispiel - oder verstehst du nur einfach nicht das ein Pointer auf deine Daten deine Kopieraktion unnötig macht?
Threads machen nicht immer Sinn und auch nicht immer alles schneller - deswegen wollen wir hier deine echte Anforderung verstehen, ein paar ints mit Threads addieren ist wirklich nichts sinnvolles
-
Skym0sh0 schrieb:
Das ist doch derselbe Code nur dass die Locks auskommentiert sind. Und ganz klar ist dann auch, dass der Code schneller läuft. Weil es echt parallel ist und nicht wie bei deinem gelockten Beispiel sequentiell.
Zu deiner Anmerkung mit den Daten kopieren:
Ja, es kommt drauf an was für ein Problem du berechnest. Wenn in jedem Schritt alle Threads/Prozesse untereinander Kilo-/Mega-/Giga-byteweise Datenaustauschen müssen, dann wird das schlecht anders gehen. Wenn es aber nur (d)eine Implementierungsungenauigkeit ist, dann könnte man da auch drum herum kommen.Aber das kommt auf das Problem an.
Der Unterschied zwischen beiden Programmen ist: ss ist in Version 2 ein Array vom Typ args und jeder Thread i bekommt sein eigenes ss[i]. Würde ich das nicht so machen, dann würden die Threads, während sie parallel laufen, miteinander wechselwirken und der Input wäre falsch. Allerdings muss ich auch meinen Input für die Funktion für jeden Thread kopieren, und das ist es, was ich nicht haben will.
-
Gast3 schrieb:
bitte nicht wieder deinen Quelltext posten - das ist keine Beschreibung und es ist auch einfach ein schlechtes Beispiel - oder verstehst du nur einfach nicht das ein Pointer auf deine Daten deine Kopieraktion unnötig macht?
Ich schätze, das war das Problem.
Jetzt funktioniert das, was ich haben will. Hätte man drauf kommen können. Ich bedanke mich. 
-
-printf ist nicht unbedingt Thread-Safe
-printf braucht laenger als das addieren
-moeglichst IO jeglicher Art in Rechen-Threads vermeidenich hoffe dein Code ist wirklich nur ein Test und deine reale Anforderung sieht voellig anders aus
-
dein
time_spent = (double)(end - begin);
ist ja nur die Zeit fuer das Thread-Erzeugen, erst nach der Join-Schleife kommt die Rechen-Zeit, die Zeit fuer 10x pthread_create wird wohl kaum bemerkbar sein
-
Also mein Programm funktioniert inzwischen im Wesentlichen.
Leider scheint der Gewinn an Rechenpower praktisch Null zu sein und ich verstehe einfach nicht, wieso. Ich habe 4 Kerne in meinem Rechner.Das Programm berechnet, wie Licht an einem Schichtsystem reflektiert wird. Ich skizziere hier nur mal den Code:
typedef struct{ Schichtdicken, Rauigkeiten, Optische Eigenschaften, Polarisation, usw. } RIpack; typedef struct{ double *Einfallswinkel RIpack *Input //Output double *R; } RI; void* Reflektivitaet(void *arg){ Hier steht die Berechnung drin. Dauer pro Ausführung ca. 1ms oder so, hängt stark vom Input ab. } int main(){ RIpack Input_Paket Der Input wird gefüllt RI Thread_Paket[Threadzahl] Start der Zeitmessung für alle Threads i{ Thread_Paket[i].Einfallswinkel=&Einfallswinkel[i] Thread_Paket[i].Input=&InputPaket Thread_Paket[i].R=&R[i] pthread_create (Thread+i, NULL, Reflektivitaet, (void*)&Thread_Paket[i]) } Threads wieder zusammenfügen Ende der Zeitmessung Die berechnete Reflektivität in ein Output-File schreiben. }Für das Ergebnis der Zeitmessung macht es leider absolut keinen Unterschied, ob ich die Threads noch innerhalb der Schleife wieder zusammenführe (Dann werden sie strikt nacheinander ausgeführt) oder ob sie parallel laufen. Das ist genau das Gegenteil von dem, was ich erwartet habe.
-
Aha
-
Gigaz schrieb:
Also mein Programm funktioniert inzwischen im Wesentlichen.
Leider scheint der Gewinn an Rechenpower praktisch Null zu sein und ich verstehe einfach nicht, wieso. Ich habe 4 Kerne in meinem Rechner.Vergesst es wieder, ich bin dahinter gekommen. Das Zusammenfügen der Threads kostet in allen Fällen 10 Mal mehr Rechenzeit als die Berechnung der Reflektivität.

-
Wie schon mehrmals gesagt worden ist:
Parallelität lohnt sich erst ab einem gewissen Rechenaufwand. 1, 2 oder auch 50000 (mehr oder weniger atomare) Rechenoperationen gehen der CPU während dem Kaffeetrinken in der Badewanne immer noch zupp von der Hand.
Wenn dein sequentielles Programm deine Reflektionsberechnungen schon innerhalb von 2-3 Sekunden schafft, dann bringt es auch nix mit 10 Threads/CPUs/Kernen dadrauf zu kloppen. Das amdahl'sche Gesetz wäre an der Stelle vielleicht interessant und damit auch der Gustaffson.
-
Das Zusammenfügen der Threads kostet in allen Fällen 10 Mal mehr Rechenzeit als die Berechnung der Reflektivität.
wie in allen Post vorher schon geschrieben kommt es da nur auf die Details an - einfach Threads auf und fertig ist nicht die Lösung
aber mir fallen noch so Sachen auf:
was ist denn die Auflösung von clock()? weil du hier von Millisekunden sprichst
"Dauer pro Ausführung ca. 1ms"wie sieht denn bitte jetzt mit den richtigen Daten dein ganzer, ablauffähiger Source aus - wenn du deine Daten einfach in zu kleine Happen zerlegst helfen dir die Threads null
falls du permanten Relefektionen berechnen willst kann du die Threads auch vorbereiten und ständig mit Daten fuellen - dann sparst du die Start-Zeit, verändert aber den Aufbau deines Programmes - und unbrauchbar wenn du nur ein paar Daten berechnen willst - warum willst du den überhaupt optimieren? oder sehen wir IMMER noch nicht deinen echten Datenumfang
ist das eine optimierte oder unoptimierte Version deines Programmes - schon zu viele Leute haben tagelang ihre Debug-Builds mit Benchmarks gequaelt
und noch viel wichtiger
sind das wirklich alles Zeiger in deinen Datenstrukturen, Cache-Misses/Alignment usw. können auch ganz schön kosten - da solltest du erstmal drann
-
Erst gibst echten Code mit Pseudo-Berechnung
=>(1)OHNE Angabe des Umfanges/Aufbaus deiner echten Daten/Algorithmusdann gibt es Pseudo Code mit Pseudo-Berechnung
=>(2)OHNE Angabe des Umfanges/Aufbaus deiner Daten/Algorithmus(3)OHNE die Angabe des Umfanges/Aufbaus deiner echten Daten/Algorithmus
kann hier keiner gute Tips geben - das ist wie so wie den PC von der Oma übers Telefon reparierendeine Fragen/Antworten/Source wirken ein wenig bastellig und unkoordiniert - du beantwortest nicht eine einzige Frage sonder schreibst nur Statusupdates
Die ist: Willst du es schneller - oder ist dir das egal
falls du es schneller willst können wir
(4)OHNE die Angabe des Umfanges/Aufbaus deiner echten Daten/Algorithmus
leider nicht wirklich richtig helfen
-
Die Reflektivitäten zu berechnen ist tatsächlich nur ein Unterprogramm, sie sollen später auch an gemessene Daten gefittet werden können.
Ich dachte mir erst, ich gebe einfach jedem Datenpunkt seinen eigenen Thread, aber das war eine schlechte Idee, wie ich gelernt habe. Ich muss und kann auf einer viel höheren Ebene parallelisieren. Also ob du's glaubst oder nicht, mir hat dieser Thread und auch du schon sehr geholfen.
-
Gigaz schrieb:
Also ob du's glaubst oder nicht, mir hat dieser Thread und auch du schon sehr geholfen.

Aber denk doch einmal an die Leute, die hier Zeit für dich opfern - je weniger informationen du gibst, desto mehr energie müssen sie investieren. Am Ende bleibt ihnen dann dein Name ein wenig schlechter in Erinnerung als er vorher war.
-
(5)OHNE die Angabe des Umfanges/Aufbaus deiner echten Daten/Algorithmus
kann dir keiner RICHTIG helfen - nur dein Datenumfang, Inhalt und Algorithmus ist entscheiden wie ein Performanzoptimierung aussieht - sei es jetzt mit Threads - aber trotzdem anderes als du es probierst oder auch einfach nur durch einen effizienteren Algorithmus, aber das scheint dich ja wirklich NICHT zu interessieren, oder du VERSTEHST es einfach nichtbtw: dein letzter Post enthielt wieder nur eine Statusberich - bisher 0 Antworten, sehr nervig
-
Ich finds ja nett dass ihr mir helfen wollt. Hier muss aber niemand Energie in irgendwas investieren, ihr macht das ist alles freiwillig. Also ist der Vorwurf, dass ich euch nerve oder eure Zeit verschwende, erstens unhöflich und zweitens völlig aus der Luft gegriffen. Ich wünsche einen guten Tag.

-
Jop, ich find den Vorwurf auch was halt los. Das schlimmste, was dir passieren kann ist, dass man dir sagt, dass dir nicht zu helfen ist ohne weitere Informationen. Und wer damit leben kann (was du ja offensichtlich kannst), dem passts. Und wer nicht, muss mehr Informationen rausgeben. Und gezwungen wird hier auch niemand etwas zu schreiben.
Oder gabs in den Nutzungsregeln 'ne Klausel ála "mindestens ein Beitrag pro Tag und Thread" ?

-
Skym0sh0 schrieb:
Oder gabs in den Nutzungsregeln 'ne Klausel ála "mindestens ein Beitrag pro Tag und Thread" ?

Nein, aber das was otze als Folge solchen Verhaltens prophezeite, nämlich dass man ganz schnell einen Ruf als Hilfsresistenter bekommt, stimmt.
-
wtf? ihr lest die Kacke noch?