Skip to content

Priprava delovnega okolja

Programsko orodje OpenMP

Programsko orodje OpenMP, ki omogoča pisanje večnitnih programov v jezikih C/C++ in FORTRAN, je sestavljeno iz dveh delov:

  • Prvi del orodja OpenMP je vdelan v sam prevajalnik. V programskih jezikih C/C++ to pomeni, da prevajalnik pozna vrsto #pragma ukazov, s katerimi programer določi, kako naj prevajalnik generira večnitno kodo.
  • Drugi del orodja OpenMP je knjižnica. Ta vsebuje podporne funkcije, ki omogočajo programerju kar najbolje izkoristiti s #pragma ukazi označeno kodo.

Za pisanje večnitnih programov z OpenMPjem v Cju potrebujemo prevajalnik za programski jezik C, ki podpira OpenMP. V okviru te delavnice bomo uporabljali prevajalnik C, ki je del GCCja (odločitev je enostavna, saj je ta prevajalnik nameščen na sistemih slovenske superračunalniške infrastrukture).

Večnitno programiranje seveda ni omejeno le na superračunlanike. Za pisanje večnitnih programov za osebne računalnike in mobilne naprave ne potrebujemo ničesar drugega kot ustrezni prevajalnik za programski jezik C:

  • GNU/Linux: prevajalnik gcc;
  • Windows 10: MVS C/C++ ali prevajalnik gcc znotraj Windows Subsystem for Linux;
  • Mac OS X: prevajalnik gcc naložen preko MacPorts ali Homebrew.
    (Privzeti Clang prevajalnikna sistemu Mac OS X pride brez podpore za OpenMP.)

Verjetno ni potrebno posebej poudariti, da pretirano zastarela verzija prevajalnika ne prinaša bonus točk.

Test delovnega okolja

Da preverimo, ali imamo na sistemu nameščen ustrezni prevajalnik, napišemo prvi program:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <stdio.h>
#include <omp.h>

int main ()
{
  printf ("Hello world:");
  #pragma omp parallel
    printf (" %d", omp_get_thread_num ());
  printf ("\n");
  return 0;
}

Program hello-world-1.c najprej izpiše znani podrav, nato pa se izvajanje programa zaradi ukaza #pragma omp parallel razdeli v niti. Ukaz velja le za naslednji stavek, s katerim vsaka nit z uporabe OpenMP funkcije omp_get_thread_num izpiše svojo oznako (zaporedno številko).

Program prevedemo z ukazom

$ gcc -fopenmp -o hello-world-1 hello-world-1.c
$
gcc -fopenmp -o hello-world-1 hello-world-1.c

Če imamo ustrezen prevajalnik, ni težav, rezultat je izvršljiva datoteka hello-world-1.
Če prevajalnik ne prevede programa, zamenjajte prevajalnik.

Na lokalnem računalniku, ki v tem konkretnem primeru podpira 12 hkrati izvajajočih se strojnih niti, poženemo program in dobimo izpis na zaslon:

$ ./hello-world-1
Hello world: 8 7 10 1 2 3 6 0 9 5 11 4  
./hello-world-1

(Ta program je povsem neobremenjujoč za sistem, zato ga lahko poženemo tudi na vozlišču nsc-login.ijs.si. Da ne motimo ostalih uporabnikov, se izvajanju ostalih programov na tem vozlišču dosledno izogibamo.)

Če želimo program izvesti v gruči, lahko to storimo z ukazom srun:

$ srun --reservation=fri --ntasks=1 --cpus-per-task=12 hello-world-1
Hello world: 6 8 1 4 2 0 11 3 7 5 10 9
srun --reservation=fri --ntasks=1 --cpus-per-task=12 hello-world-1

V tem primeru smo zagnali program kot en proces (--ntasks=1) in mu omogočili uporabo 12 strojnih niti (--cpus-per-task=12).

Vaja

Prevedite in poženite program hello-world-1.c.
Poženite ga večkrat zaporedoma. Zakaj dobite vsakič drugačen izpis?