Open MPI - Schleife parallelisieren



  • Hallo,

    ich möchte in meinem Programm Schleifen parallelisieren und dafür OpenMPI nutzen. Das tatsächliche Programm ist wesentlich komplexer, aber ich habe hier mal ein einfaches, leider nicht funktionierende (wird nur seriell ausgeführt) Beispiel erstellt:

    #include <iostream>
    #include <time.h>
    #include <omp.h>
    #define N 1e6
    
    using namespace std;
    
    class DoSomething{
    public:
    	static int DoParallel(){
    		unsigned long i = 0, j = 0, k = 0;
    #pragma omp parallel nowait num_threads(3) for
    		for (i = 0; i < 1000; i++){
    			for (j = 0; j < N; j++){
    				k++;
    			}
    			for (j = 0; j < N; j++){
    				k--;
    			}
    		}
    		cout << "k: " << k << endl;
    		return 0;
    	}
    };
    
    int main(){
    	time_t start = time(NULL), stop;
    	cout << "Go!"<< endl;
    
    	DoSomething::DoParallel();
    
    	cout << "Required wall clock time: " << difftime(stop = time(NULL), start) << " sec." << endl << endl;	
    	getchar();
    	return 0;
    }
    

    Also, das Programm wird ausgeführt, der Rechner benötigt etwa 4 Sekunden... aber die CPU Leistung bleibt bei meinem Vierkerner bei 25% statt erwartete 75%.
    Kann es daran liegen, dass ich die Variablen nicht als share, firstprivate, private, lastprivate definiert habe - aber das sollte nicht nötig sein?
    Sieht jemand den Fehler?

    Ps.: Auch wenn ich die parallele Schleife in folgenden Ausdruck packe, funktioniert es nicht:

    #pragma omp parallel
    		{
    
    }
    

    Vielen Dank für Eure Mühe.



  • In deiner Schleife wird eine einzige Variable manipuliert. Da kann nicht nur OMP nichts, da kann niemand etwas parallelisieren.



  • Wieso hat das damit etwas zutun? In meinem Programm wird eine Liste durchlaufen. 2 Mio. Elemente und für jedes Element soll ein komplexer Berechnungsprozess durchgeführt werden. Den wollte ich einfach durch das in- und decrementieren von k simulieren.

    Das Programm macht natürlich keinen Sinn... Es soll einfach 1000 mal, bzw.
    3 * 333 mal ein lokaler wert k rauf und runter gezählt werden. Im korrigierten Beispiel ist die Variable k jetzt lokal - aber es läuft trotzdem nur seriel.

    class DoSomething{
    public:
    	static int DoParallel(){
    		unsigned long i = 0;
    
    #pragma omp parallel for nowait num_threads(3) 
    			for (i = 0; i < 1000; i++){
    				Process();
    			}
    			return 0;
    		}
    
    private:
    	static int Process(){
    		unsigned long j = 0, k = 0;
    
    		for (j = 0; j < N; j++){
    			k++;
    		}
    		for (j = 0; j < N; j++){
    			k--;
    		}
    		return 0;
    	}
    };
    


  • ...zusammen hängt, wenn vier Threads eine Variable bearbeiten - gleichzeitig.
    Aber im korrigierten Beispiel sind die Variablen lokal für jeden Thread anders... und es läuft noch immer nur seriel.



  • Disclaimer: Ich stecke jetzt in OMP nicht wirklich drin.

    Unter Windows sagt mir der Task-Manager (unter Linux gibt's garantiert 'n Äquivalent) wieviele Threads ein Prozess am Laufen hat. Schau doch mal da.



  • Der zeigt 25% an - also seriel.



  • Das sagt nichts über die Anzahl der laufenden Threads aus!
    ~Du magst recht haben, aber bis jetzt glaubst Du es nur. Warum willst Du dich nicht vergewissern?~



  • class DoSomething{
    public:
    	static int DoParallel(){
    		int i = 0, j = 0;
    #pragma omp parallel
    		{
    #pragma omp parallel for nowait num_threads(3) 
    			for (i = 0; i < 1000; i++){
    				cout << "Process done by thread number " << omp_get_thread_num() << endl; //Output of thread number
    				Process();
    			}
    		}
    			return 0;
    		}
    
    private:
    	static int Process(){
    		int j = 0, k = 0;
    
    		for (j = 0; j < N; j++){
    			k++;
    		}
    		for (j = 0; j < N; j++){
    			k--;
    		}
    		return 0;
    	}
    };
    

    Das Programm gibt nur "Process done by thread number 0" aus.

    Und wenn Du vier Kerne hast, und bei diesem Programm nur einer arbeitet, dann zeigt der TM 25% an...



  • Ohje, hab gerade auf Wikipedia über OpenMPI folgendes gelesen:

    "OpenMP ist in den meisten Compilern integriert.

    ➡ Microsoft Visual C++ 2005, 2008 und 2010 (Professional, Team System, Premium und Ultimate Edition) ⚠ ⚠ ,
    ➡ Intel Parallel Studio für verschiedene Prozessoren (OpenMP 3.1 seit Version 13),
    ➡ GCC seit Version 4.2 (OpenMP 3.1 seit Version 4.7),
    ➡ Oracle Solaris Studio Compiler und Tools für Solaris OS (UltraSPARC und x86/x64) und Linux,
    ➡ Fortran, C und C++ Compiler der Portland Group (OpenMP 2.5),
    ➡ IBM XL C/C++ compiler,
    ➡ Nanos Compiler
    "

    Ich hab nur die kostenlose Express Version.

    Kann das jemand so bestätigen, denn Wikipedia muss nicht immer recht haben und mein Kompiler gibt keinen Fehler aus. Die OMP.h-header war standardmäßig verfügbar über #include <omp.h>



  • /openmp muss in die Kompiler-Befehlszeile.


Anmelden zum Antworten