A GCC a 4.2 verzió óta tudja az OpenMP-t. Engem ez meglepett, mert az OpenMP #pragmákkal működik, és az utolsó tapasztalatom szerint a GCC nem szereti a pragmákat. Tényleg fura, hogy valamit teljesen a fordítóra bíznak, ki hogy akarja csinálni, de úgy tűnik az évek alatt hozzászoktak a gondolathoz. Mindenesetre azt mondják, hogy a GCC platformfüggetlenségéhez jól passzol az OpenMP. Ez pedig jogos.
Mármost, mint friss kétmagos processzor tulajdonos, viszketett a markom, hogy csak ki kéne próbálni a párhuzamosságot ezzel a cuccal. Korábban játszottam párhuzamos programozással PVM-ben egyetemi beadandók erejéig, meg SDL féle szálakkal, de az OpenMP eleganciája lenyűgözött, úgyhogy most ezzel kell.
Na most ez nem sétagalopp. A legfrissebb hivatalos MINGW-ben jelenleg a 4.1.2-es GCC van, amiben még nincs OpenMP. Úgyhogy le kellett rántani a alpha tesztes 4.3-asat. A friss hivatalos MINGW-t szépen lemásoltam, és az 4.3-assal amit lehetett, felülírtam.
Jött a parancs, hogy
C:\gcc430a\bin\g++.exe -fopenmp main.cpp
De ez fordítási hibával leállt:c:/gcc430a/bin/../lib/gcc/mingw32/4.3.0/libgomp.a(parallel.o): (.text+0xe): undefined reference to `_imp__pthread_getspecific'
...
A hiba lényege, hogy nem csatolt kellőképpen libeket egy rosszul beállított .spec miatt.A hibát okozó file:
lib\gcc\mingw32\4.3.0\libgomp.spec
A tartalma helyesen (érdekes módon egy francia oldalon találtam rá, most már francia mellett magyarul is fent van a neten:D) :
# This spec file is read by gcc when linking. It is used to specify the
# standard libraries we need in order to link with -fopenmp.
*link_gomp: -lgomp -lpthread
És így már megy is.
Itt egy tesztprogram, hogy meg lehessen nézni, hogy működik-e:
/****************************************************************
* FILE: omp_hello.c
* DESCRIPTION:
* OpenMP Example - Hello World - C/C++ Version
* In this simple example, the master thread forks a parallel region.
* All threads in the team obtain their unique thread number and print it.
* The master thread only prints the total number of threads. Two OpenMP
* library routines are used to obtain the number of threads and each
* thread's number.
* AUTHOR: Blaise Barney 5/99
* LAST REVISED: 04/06/05
****************************************************************/
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
int main (int argc, char *argv[]) {
int nthreads, tid;
/* Fork a team of threads giving them their own copies of variables */
#pragma omp parallel private(nthreads, tid)
{
/* Obtain thread number */
tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid);
/* Only master thread does this */
if (tid == 0)
{
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads);
}
//everybody work for a while
double d;
for (int i=0;i<1000000000;i++) {
d += sqrt(i);
if (i%100000000==0) printf("(%d %d) ",i/100000000,tid);
}
} /* All threads join master thread and disband */
}
Magyarázat: A hivatalos példaprogramot kicsit átalakítottam, hogy meg lehessen nézni két dolgot. Az egyik, hogy mindkét procit láthatóan terheli-e (igen), a másik, hogy a párhuzamos blokkokban deklarált változók szál-privátak-e. Az int i a blokkban jól működik, amire bizonyíték, hogy mindkét szál (kétmagoson) mind a 10 alkalommal kiírja az értékét. Ha a két szál ugyanazt a változót használná, ennek a valószínűsége ilyen körülmények között igen alacsony.Úgy érzem, hamarosan felturbózom a neuronháló tanító programot párhuzamosra! :)