Mehrkernanwendung möglich/passender Einstieg



  • Ich denke, ihr übertreibt alle ziemlich. Gerade reine Berechnungen sind relativ einfach zu parallelisieren und erzielen auch proportionale Performance.
    Solange du unter C++11 kompilierst, sollte auch dein OS egal sein.

    Wenn du einfach nur eine Schleife parallelisieren willst, reicht dafuer eine Zeile OpenMP. "#pragma omp parallel for", fertig. Ansonsten waere es gut, wenn du Code zeigen koenntest, damit wir dir besser helfen koennen.



  • Ja, genau das ist doch unser Reden. Aber es kommt ja kein Code und keien Antwort...



  • Teilweise braucht man doch selber gar nichts machen? Es gibt doch von Intel Precompiler-Makros die man nur um die Schleife setzen braucht, und der Rest geht von alleine.
    Selbst im MS-Compiler ist das mittlerweile verfügbar.

    http://de.wikipedia.org/wiki/OpenMP#Beispiel-Code



  • Klar, aber trotzdem muss/sollte man sich ein paar Gedanken darum machen.
    Denn alles ist nicht so ohne Weiteres parallelisierbar.

    Item * top = // ... gefüllte verkette Liste
    
    Item * current = top;
    while ( current != nullptr )
    {
    	current->someFunc(); // teuer
    	current = current->next;
    }
    

    Nicht so mal eben mit #pragma omp parallel machbar...
    (Und ja, den Trick bzw. die Lösung kenne ich auch, schwer ists ja nicht)



  • (Und ja, den Trick bzw. die Lösung kenne ich auch, schwer ists ja nicht)

    Die da wäre? Rein interessehalber.



  • Item * top = // ... gefüllte verkette Liste
    // ...
    Item * items[size]; 
    Item * current = top;
    uint i = 0;
    while ( current != nullptr )
    {
    	items[i++] = current;
        current = current->next;
    }
    // ..
    #pragma omp parallel for
    for(int i = 0; i < size; i++)
    	items[i]->someFunc();
    

    Lohnt sich natürlich nur wenn die aufzurufende Funktion teuer genug ist...



  • Hab mich jetzt mal ein bisschen mit openMP gepsielt.
    Also prinzipell bedeutet das aufteilen auf mehrer Threads, bzw. die verwendung von z.B.:

    #pragma omp parallel for
    

    nicht unbedingt mehr "Geschwindigkeit" oder?

    #pragma omp for 
    for (int i = 0; i < 100000; i++){
    
       std::cout << "Here comes i : " << i << "\n";
    }
    

    ist jetzt nicht unbedingt schneller wie ohne #pragma omp for ??



  • du solltest dir überlegen wie du es machen möchtest, also ob ein datenaustausch zwischen den threads stattfinden soll...

    ansonsten ein paar c++ threads: 😃 (kommt halt drauf an was und wie du ein problem lösen willst welcher für dich passen könnte)

    std::thread -> c++11
    async -> asynchrone threads
    pthreads ...

    ansonsten gab es auch noch threads denen du die kerne deiner Hardware festzuweisen kannst... also z.b. kern 1 macht das ... etc... da weiß ich jetzt aber gerade nicht wie die funktion heißt... sry hab auch keine zeit für ne kurze recherche... 🙄

    ich kann dir nur eines von diesen empfehlen ...
    man findet viel information unter google dazu und syntaktisch komplex ist es auch nicht wirklich...
    hoffe ich konnte dir wenigstens ein bisschen helfen... 😉



  • du kannst dich auch mit den themen:

    synchrone threads, asynchrone threads
    was ist das?
    unterschiede?

    was ist paralellisierung und wozu kan man threads benutzen?

    mir hat das damals als ich angefangen habe sehr geholfen... 🙂
    vorallem welche thread- möglichkeit man nutzt und welche besser nicht...



  • unsure110 schrieb:

    Hab mich jetzt mal ein bisschen mit openMP gepsielt.
    Also prinzipell bedeutet das aufteilen auf mehrer Threads, bzw. die verwendung von z.B.:

    #pragma omp parallel for
    

    nicht unbedingt mehr "Geschwindigkeit" oder?

    #pragma omp for 
    for (int i = 0; i < 100000; i++){
    
       std::cout << "Here comes i : " << i << "\n";
    }
    

    ist jetzt nicht unbedingt schneller wie ohne #pragma omp for ??

    Wie gesagt, das kommt drauf an.
    Dein Beispiel hier ist kein gutes Beispiel, da du zum ersten Seiteneffekte hast (die Bildschirmausgabe) und zum zweiten die Consolenausgabe eben ganz tief intern doch mit sowas umgehen kann. D.h. du hast doch eine Synchronisation, was ein dickes Performanceminus aufwirft. Und zum dritten, wähle Zahlen die hinreichend groß genug sind. Bis 100000 zählen kann auch mein Taschenrechner in 0,nix. Und zum vierten reicht #pragma omp for nicht aus, das muss entweder in einem parallel-Block liegen oder #pragma omp parallel for heissen.

    Probier einfach mal dieses (Mehr oder weniger sinnlose) Programm. Den Parameter p kannst du nach belieben verändern:

    #include <iostream>
    #include <chrono>
    #include <vector>
    
    #include <omp.h>
    
    int func(int n)
    {
    	int r = 0;
    	for (int i = 0; i < n; i++)
    	{
    		if (i % 2 == 0)
    			r += i;
    		else
    			r -= i;
    	}
    
    	return r;
    }
    
    int main()
    {
    	const int p = 8;
    
    	int N = 100000;
    	std::vector<int> vec(N);
    
    	if ( !(p < 1 ))
    		omp_set_num_threads(p);
    
    	auto t1 = std::chrono::high_resolution_clock::now();
    	{
    #pragma omp parallel for
    		for (int i = 0; i < vec.size(); i++)
    		{
    			vec[i] = func(i);
    		}
    
    		int result = 0;
    #pragma omp parallel for reduction(+:result)
    		for (int i = 0; i < vec.size(); i++)
    			result += vec[i];
    
    		std::cout << "R: " << result << std::endl;
    	}
    	auto t2 = std::chrono::high_resolution_clock::now();
    
    	auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1).count();
    
    	std::cout << "Duration: " << duration << std::endl;
    
    	return 0;
    }
    


  • @Kellerautomat
    Ich glaube du hattest noch keinen Kontakt mit diversen Stolpersteinen und stellst dir die Sache daher etwas zu einfach vor.
    Oder hast sie einfach nicht bemerkt - gerade beim Thema Threads kann man viele Fehler jahrelang in einem Programm haben ohne draufzukommen.

    Klar geht es manchmal einfach.
    Wenn der Auto-Parallelizer es packt, fein.

    Ansonsten... einfach mal #pragma omp parallel for vor den Loop packen und gut. Oder eigentlich weniger gut. Es sei denn man findet Schmerzen und schwer bis gar nicht reproduzierbare Fehler gut.
    Man muss schon verstehen was man mit OpenMP tut. Und das lernt man halt nicht im Schlaf.



  • unsure110 schrieb:

    H

    #pragma omp for 
    for (int i = 0; i < 100000; i++){
    
       std::cout << "Here comes i : " << i << "\n";
    }
    

    ist jetzt nicht unbedingt schneller wie ohne #pragma omp for ??

    Da ist wahrscheinlich die Konsolen-Ausgabe der Flaschenhals. Mach mal ein paar Berechnungen ohne Ausgabe... und gebe die verbrauchte Zeit aus.



  • Wenn es wirklich der Fall sein sollte, dass man nur eine große Schleife parallelisieren möchte sollte OpenMP das Mittel der Wahl sein, da am nächsten am Problem dran. Das "einzige" was man dazu noch wissen muss ist: Welche Variablen müssen Thread-lokal und welche gemeinsam sein und wie bekomme ich die Daten am Schluss wieder wie gewünscht zusammen. In einfachen fällen weiß man das nach einem kurzen Tutorial.



  • Wenn es wirklich der Fall sein sollte, dass man nur eine große Schleife parallelisieren möchte sollte OpenMP das Mittel der Wahl sein, da am nächsten am Problem dran. Das "einzige" was man dazu noch wissen muss ist: Welche Variablen müssen Thread-lokal und welche gemeinsam sein und wie bekomme ich die Daten am Schluss wieder wie gewünscht zusammen. In einfachen fällen weiß man das nach einem kurzen Tutorial.

    Und

    Dein Beispiel hier ist kein gutes Beispiel, da du zum ersten Seiteneffekte hast (die Bildschirmausgabe) und zum zweiten die Consolenausgabe eben ganz tief intern doch mit sowas umgehen kann. D.h. du hast doch eine Synchronisation, was ein dickes Performanceminus aufwirft. Und zum dritten, wähle Zahlen die hinreichend groß genug sind. Bis 100000 zählen kann auch mein Taschenrechner in 0,nix. Und zum vierten reicht #pragma omp for nicht aus, das muss entweder in einem parallel-Block liegen oder #pragma omp parallel for heissen.

    Ehrlich gesagt ich hab mich nicht eingelesen, sondern nur den wikipedia Artikel überflogen und der größte Kampf war meiner IDE zu erklären wie sie das ganze Compliieren muss 🙂

    Ist aber ziemlich interssant, werd mich da mal einlesen, obwohl ich das wohl nie brauchen werde 🙂

    Hat jmd. ein empfehlenswertes Tutorial zu der Thematik?



  • unsure110 schrieb:

    Hat jmd. ein empfehlenswertes Tutorial zu der Thematik?

    Ja, besuch die entsprechendeN VorlesungEN an der nächsten Uni 😃

    Hier im Forum gibts nen kleinen Artikel über OpenMP.

    Ich hab irgendwie das Gefühl meine Beiträge werden ignoriert 😃

    Artchi schrieb:

    unsure110 schrieb:

    H

    #pragma omp for 
    for (int i = 0; i < 100000; i++){
    
       std::cout << "Here comes i : " << i << "\n";
    }
    

    ist jetzt nicht unbedingt schneller wie ohne #pragma omp for ??

    Da ist wahrscheinlich die Konsolen-Ausgabe der Flaschenhals. Mach mal ein paar Berechnungen ohne Ausgabe... und gebe die verbrauchte Zeit aus.

    😃



  • Ja, besuch die entsprechendeN VorlesungEN an der nächsten Uni

    Naja, da muss es eine bessere Lösung geben



  • unsure110 schrieb:

    Ja, besuch die entsprechendeN VorlesungEN an der nächsten Uni

    Naja, da muss es eine bessere Lösung geben

    Entsprechende Literatur lesen, fiele mir noch ein. -> 2 Min Google Hier
    Edit: Sutter hat noch einiges zur Parallelität
    http://herbsutter.com/2014/01/06/gotw-95-thread-safety-and-synchronization/
    http://herbsutter.com/category/concurrency/


Anmelden zum Antworten