» »

[C++] OpenMP težave

[C++] OpenMP težave

Arto ::

EDIT:
Napaka popravljena, ampak še vedno potrebuje zadeva več časa pri paralelni metodi kot pri sekvenčni.

// OpenMP.cpp : Defines the entry point for the console application.
//

#include "stdlib.h"
#include "stdio.h"
#include "Windows.h"
#include "time.h"
#include "omp.h"
#define N 50000000
#define N_THREADS 2



int max_num(int a_size, int a[]){
	int i;
	int max = 0;

	for(i=0; i<a_size; i++){
		if(a[i] > max) max = a[i];
	}

	return max;
}

int max_num_p(int a_size, int a[]){
	int i, tn, max[N_THREADS];
	//omp_set_num_threads(N_THREADS);

	#pragma omp parallel for shared(a,max) private(tn)
	for(i=0; i<a_size; i++){
		//if(i==1)printf("Num: %d\n", omp_get_num_threads());
		tn = omp_get_thread_num();
		//printf("Thread %d - i=%d\n", tn, i);
		if(max[tn]<a[i]){
			max[tn]=a[i];
		}
	}

	/*for(i=0; i<N_THREADS; i++){
		printf("%d\n", max[i]);
	}*/
	return max_num(N_THREADS, max);
}

void fill_random(int a_size, int a[]){
	int i;
	srand( time(NULL) );
	for(i=0; i<a_size; i++){
		a[i]=rand();
	}
}

int main(int argc, char * argv[])
{
	int start,stop, time;
	
	int * a;
	a = (int *)malloc(N * sizeof(int));
	int max;

	fill_random(N, a);
	printf("Start:\n");
	start = clock();
		max = max_num(N, a);
	stop = clock();
	time = stop-start;

	printf("%d t:%d\n", max, time);

	start = clock();
		max = max_num_p(N, a);
	stop = clock();
	time = stop-start;

	printf("%d t:%d\n", max, time);
	
	free(a);
	system("pause");
	return 0;
}



  • spremenil: Arto ()

Rokm ::

Namesto
#pragma omp parallel for shared(a,max) private(tn)

uporabi
#pragma omp parallel for private(tn)


Največja potrata pri tvojem programu je da OpenMP zaradi uporabe shared naredi lock na dostop do celotnih tabel a in max. Tako v bistvu spremeniš svoj program v zaporeden saj različne niti čakajo ena na drugo da dobijo dostop do tabele. To pa ni potrebno saj dve različni niti nikoli ne pišeta v isto lokacijo v tabeli a ali v tabeli max. Niti so tako neodvisne saj ne posegajo med seboj v vhodne ali pa v izhodne podatke.

Zgodovina sprememb…

  • spremenil: Rokm ()

Arto ::

Hvala za odgovor!
Ugotovil sem, da je bila glavna napaka, da metoda omp_get_thread_num porabi precej časa. Kolega mi je svetoval, naj popravim takole:
int max_num_p(int a_size, int a[]){
	int i, tn, max[N_THREADS];
	omp_set_num_threads(N_THREADS);

	#pragma omp parallel private(tn)
	{
		tn = omp_get_thread_num();
		#pragma omp for
		for(i=0; i<a_size; i++){
			if(max[tn]<a[i]) max[tn]=a[i];
		}
	}

	return max_num(N_THREADS, max);
}


Zadeva je zdaj hitrejša (pohitritev je okrog 1.3x), Je pa hecno, da praktično nima veze, če dam pri for zanki shared(a,max) ali ne.

Rokm ::

Čudno! Meni z odstranitvijo shared(max, a) deluje hitreje. Je pa res da poganjam to na linux mašini compajlano z mpicc, tako da mogoče se pri teki uporabijo kakšne optimizacije.
Očitno more biti nekaj takega saj če poskusim gcc -O3 tudi pri meni ni razlike med verzijo s shared ali brez.

Arto ::

Jaz kompajlam v Visual Studio 2010. Verjetno je res kakšen hec pri optimizaciji pri samem kompilanju.

Gemm ::

Ko poganjam tale kos kode (s popravkom ki get_thread_num premakne ven iz zanke), opazim da mi v nobenem trenutku ne zabije več kot enega jedra - sumim da dela na neki točki lock na tabelo a, kot je Rokm namignil. Testirano na linuksih z GCC in LLVM.. to bi tudi mene zanimalo kaj se to dogaja, ker precej pogosto uporabljam OpenMP in bi se rad izognil tovrstnim presenečenjem.

Rokm ::

Čudno! Meni pri uporabi -O3 opcije za prevajanje teče vzporedna koda približno trikrat hitreje kot zaporedna (na računalniku z osmimi jedri). Se tudi opazi poraba procesarja, ki skoči na 800% procentov, če povečaš N.

Mogoče povečane porabe ne opaziš ker se sprememba zgodi prehitro?
Če poženeš program s time se ob uporabi večih niti zna zgoditi, da je user time večji kot real time.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[Java - DN] Naključna števila

Oddelek: Šola
121341 (870) nyler
»

Java passing

Oddelek: Programiranje
203532 (3185) mihibo5
»

c napaka .c:4:1: error: expected identifier or '(' before '{' token

Oddelek: Programiranje
141912 (1485) MrStein
»

[C++] velikost matrike

Oddelek: Programiranje
191684 (1496) Jean-Paul
»

srand in program v Cju???

Oddelek: Programiranje
131568 (1438) nuclear

Več podobnih tem