Όλο και πιο συχνά ακούγεται στις μέρες μας ο όρος parallel computing, παράλληλοι υπολογισμοί, και έχει γίνει πλέον και στους προσωπικούς υπολογιστές πραγματικότητα με επεξεργαστές διπλών και τρίδιπλων (όπως το λαϊκό) επεξεργαστών. Αλλά ποιος ο λόγος και υπάρχει πράγματι κέρδος από τους επεξεργαστές με δύο πυρήνες ή είναι απλώς ένα εμπορικό παιχνίδι των εταιριών για να αυξήσουν τα κέρδη τους; Αυτή την ερώτηση δυστυχώς αδυνατώ να απαντήσω αλλά θα σας δώσω μια απλή γεύση του πως μπορούμε να εκμεταλλευτούμε αυτή τη δυνατότητα.
Oι παράλληλοι υπολογιστές χωρίζονται σε δύο βασικές κατηγορίες (επιτρέψτε μου την αγγλική ορολογία): shared και distributed μνήμης υπολογιστές. Οι πρώτοι, shared memory, είναι αυτοί που έχουμε στους υπολογιστές μας, όπου ο κάθε επεξεργαστής (στο σημείο αυτό δε θα τους ξεχωρήσω από τους πυρήνες) μοιράζεται την ίδια μνήμη με όλους τους υπόλοιπους. Οι distributed memory υπολογιστές έχουν ο καθένας δική του μνήμη και επικοινωνούν μέσω δικτύου. Προφανώς αν έχουμε 100 επεξεργαστές είναι λίγο δύσκολο να τους καλωδιώσουμε ώστε να μοιράζονται την ίδια μνήμη, ίσως στο μέλλον. Η δημιουργια, ο προγραμματισμός και η χρήση distributed memory είναι αρκετά προχωρημένη και δε θα ασχοληθω εδώ καθόλου.
Ας συνεχίσουμε λοιπόν με shared memory υπολογιστές. Για τα παρακάτω θα χρειαστούν:
sudo apt-get install build-essential libgomp
build-essential περιέχει όλα τα απαραίτητα πακέτα για προγραμματισμό και αναπτυξη κώδικα
libgomp περιέχει τη βιβλιοθήκη για shared memory parallel programming
Aναλυτικές οδηγίες για την gnu openMP μπορούν να βρεθούν http://gcc.gnu.org/onlinedocs/libgomp/
Θα ξεκινήσω με ένα απλό hello world πρόγραμμα σε C. Δημιοργούμε καταρχήν ένα φάκελο
mkdir ~/testgomp
cd ~/testgomp
Ανοίγουμε μέσα στο φάκελο testgomp με το gedit το αρχείο hello.c
gedit hello.c &
Kαι εισάγουμε τα παρακάτω:
int main()
{
printf("Hello world\n");
}
To μεταγλωττίζουμε και δημιουργούμε το εκτελέσιμο με:
gcc -c hello.c
gcc -o serialtest hello.o
Eκτελούμε το πρόγραμμα που δημιουργήθηκε με
./serialtest
και βλέπουμε ότι εκτυπώνεται στην οθόνη Hello world μόνο μία φορά.
Tώρα προσθέτουμε τη γραμμή #pragma omp parallel δηλαδή το αρχείο θα πρέπει να φαίνεται:
int main()
{
#pragma omp parallel
printf("Hello world\n");
}
To μεταγλωττίζουμε (τώρα χρειάζεται να συνδέσουμε επίσης την αντίστοιχη βιβλιοθήκη) και δημιουργούμε το εκτελέσιμο με:
gcc -c -fopenmp hello.c
gcc -o paralleltest hello.o
Εκτελούμε τώρα το παράλληλο πρόγραμμα με
./paralleltest
και βλέπουμε να τυπώνεται δύο φορές ενώ υπάρχει μόνο μία φορά στον κώδικά μας και δεν υπάρχει φυσικά κανένας βρόγχος. (Φυσικά αν έχουμε επεξεργαστή με ένα μόνο πυρήνα δε θα δούμε διαφορά)
Η γραμμή #pragma omp parallel αντιλαμβάνεται από το μεταγλωττιστή gcc σαν σχόλιο αν δεν υπάρχει η επιλογή -fopenmp κατά τη μεταγλώττιση, πράμα που επιτρέπει ένα πρόγραμμα που γράφουμε να είναι αρκετά portable.
Φυσικά αυτό δεν είναι και πολύ χρήσιμο γιατί επαναλαμβάνει την ίδια δουλειά δύο φορές. Εμείς χρειαζόμαστε κάτι που να μοιράζει το φόρτιο εργασίας στους δύο επεξεργαστές.
Aς δημιουργήσουμε τώρα ένα άλλο αρχείο hello2.c που θα περιέχει τα εξης:
#define N 100000
int main()
{
int i, a[N];
#pragma omp parallel for
for (i=0;i< style="font-weight: bold;"> a[i]= 2*i;
return 0;
}
Και μεταγλώττιση όπως πάντα με
gcc -c -fopenmp hello2.c
gcc -o paralleltest2 hello2.o
Το συγκεκριμένο παράδειγμα μοιράζει αυτόματα το array a[N] στα δύο threads που δημιουργούνται. Τα αποτελέσματα είναι σωστά γιατί το δεξί μέλος της ισότητας δεν εξαρτώνται από το αριστερό.
Aν είχαμε όμως κάτι όπως αυτό:
#define N 100000
int main()
{
int i, a[N];
a[0]=0;
#pragma omp parallel for
for (i=1; i<> a[i]= a[i-1]+1;
return 0;
}
δε θα λειτουργούσε γιατι κάθε επόμενο στοιχείο του a θα εξαρτάται από το προηγούμενο, αρα για να υπολογισει το στοιχειο 50000 στο δεύτερο thread θα χρειάζεται το 49999 από το πρώτο thread το οποίο δεν έχει υπολογιστεί ακομη.
Σε distributed memory υπολογιστές όπου τα δεδομένα, το a στο παράδειγμά μας, δεν είναι σε κοινή μνήμη θα πρέπει να μεταφέρονται από επεξεργαστή σε επεξεργαστή (για περισσότερες πληροφοριές δες http://en.wikipedia.org/wiki/Message_Passing_Interface) Yπάρχουν διάφορα εργαλεία για να στηθεί ένα [/url=http://en.wikipedia.org/wiki/Computer_cluster]cluster[/url] (distributed memory υπολογιστής) φυσικά και σε linux.
Βιβλιογραφία
1. http://openmp.org/wp/
2. http://gcc.gnu.org/onlinedocs/libgomp/
3. http://en.wikipedia.org/wiki/OpenMP
4. http://en.wikipedia.org/wiki/Parallel_computing