Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 17/09/2010, à 14:52

Wacken

[PYTHON] [RESOLU] "Dérouler" une boucle facilement ?

Salut à tous,

Je me suis récemment mis à la programmation en parallèle avec OpenMP (C++), et je cherche à faire pareil avec Python. Ma demande est basique, à savoir "dérouler" une boucle. En C++, il suffit d'ajouter :

#pragma omp parallel for

for (int i=0; i<max; i++){
    tab[i] = .....
}

#pragma omp barrier

Et la boucle est automatiquement parallélisée sur le nombre de CPU disponibles. Avec Python, je n'arrive pas à faire pareil (du moins, pas aussi simplement). Pour lemoment, je fais :

	def Center_of_Masses_MT(self, molecules=[0], verb=2):
		import multiprocessing
			
		mutex = multiprocessing.Lock()
		ps = []
		
		parent_1, child_1 = multiprocessing.Pipe()
		parent_2, child_2 = multiprocessing.Pipe()

		p = multiprocessing.Process(target = self.Center_of_Masses_MT_thread, args = (mutex, child_1, mol, 0, int(self.n_frame/2), verb))
		ps.append(p)
		p.start()

		p = multiprocessing.Process(target = self.Center_of_Masses_MT_thread, args = (mutex, child_2, mol, int(self.n_frame/2), self.n_frame, verb))
		ps.append(p)
		p.start()
		
		res_thr1 = parent_1.recv()
		res_thr2 = parent_2.recv()
		
		for x in ps:
			p.join()
		self.CM_x[0:int(self.n_frame/2)] = res_thr1[1][:]
		self.CM_x[int(self.n_frame/2):] = res_thr2[1][:]
			
	
	def Center_of_Masses_MT_thread(self, mutex, child, mol, frame_i, frame_f, verb):	

		for i in xrange(frame_i, frame_f, 1):
			for ii in mol:
				M_TOT = 0.0
				for iii in xrange(self.n_atom[ii]):
					self.CM_x[i,ii] += self.atomic_mass[i, ii, iii] * self.x[i, ii, iii]
		
		child.send([self.CM_x[frame_i:frame_f]])
		child.close()

En gros, si je veux paralléliser sur 2 CPU, je divise manuellement mon tableau en 2, je traite chaque partie du tableau sur un CPU, puis je remets ensemble. Bon, ça marche, mais si j'ai 4 CPU à disposition, je recode tout sur base de 4 CPU ? C'est pas super pratique...

Vous auriez une astuce ?

Merci !

Dernière modification par Wacken (Le 18/09/2010, à 14:36)

Hors ligne

#2 Le 17/09/2010, à 22:04

Jules Petibidon

Re : [PYTHON] [RESOLU] "Dérouler" une boucle facilement ?

Suis une quiche en Python, j'apprends (et tu proposes un exo sympa wink ), donc désolé si je tombe à coté. Mais un truc de ce style ne conviendrait pas ? (à remettre en forme avec tes variables, j'ai pas tout copié)

longueurSousTableaux = len( leTableauAAnalyser ) / nbProcesseurs
parents = []
childs = []
ps = []
res_thr = []
for np in range( 0 , nbProcesseurs ):
	pipe = multiprocessing.Pipe()
	parents.append( pipe )
	childs.append( pipe )
	
	borneMin = longueurSousTableaux * np
	borneMax = longueurSousTableaux * ( np + 1 )

	p = multiprocessing.Process( target = '...' , arg = ( '...' , '...' , '...' , borneMin , borneMax , '...' )
	ps.append( p )
	p.start()

	res_thr.append( parent[ np ].recv() )

Dernière modification par Jules Petibidon (Le 17/09/2010, à 22:05)

Hors ligne

#3 Le 18/09/2010, à 11:44

Wacken

Re : [PYTHON] [RESOLU] "Dérouler" une boucle facilement ?

Jules Petibidon a écrit :

Suis une quiche en Python, j'apprends (et tu proposes un exo sympa wink ), donc désolé si je tombe à coté. Mais un truc de ce style ne conviendrait pas ? (à remettre en forme avec tes variables, j'ai pas tout copié)

longueurSousTableaux = len( leTableauAAnalyser ) / nbProcesseurs
parents = []
childs = []
ps = []
res_thr = []
for np in range( 0 , nbProcesseurs ):
	pipe = multiprocessing.Pipe()
	parents.append( pipe )
	childs.append( pipe )
	
	borneMin = longueurSousTableaux * np
	borneMax = longueurSousTableaux * ( np + 1 )

	p = multiprocessing.Process( target = '...' , arg = ( '...' , '...' , '...' , borneMin , borneMax , '...' )
	ps.append( p )
	p.start()

	res_thr.append( parent[ np ].recv() )

Pas bête d'utiliser une liste de threads ! Je teste ça lundi, et je te tiens au jus wink

Merci !

Hors ligne

#4 Le 18/09/2010, à 14:35

Wacken

Re : [PYTHON] [RESOLU] "Dérouler" une boucle facilement ?

Voilà la solution, proche de ce que tu as proposé :

		mutex = multiprocessing.Lock()
		ps = []
		len_subtable = int(self.n_frame/n_cpu) + 1	
		parents = []
		childs = []
		res_thr = []

		for np in range(n_cpu):
			pipe = multiprocessing.Pipe()
			parents.append(" ")
			childs.append(" ")
			parents[np], childs[np] = pipe
			
			min = len_subtable * np
			max = len_subtable * (np+1)
			if max > self.n_frame:
				max = self.n_frame

			p = multiprocessing.Process(target = self.Center_of_Masses_MT_thread, args = (mutex, childs[np], mol, min, max, verb))
			ps.append(p)
			p.start()

		for np in range(n_cpu):
			res_thr.append(parents[np].recv())
		
		for x in ps:
			p.join()
		
		for np in range(n_cpu):
			min = len_subtable * np
			max = len_subtable * (np+1)
			if max > self.n_frame:
				max = self.n_frame

			self.n_electrons[min:max] = res_thr[np][0][:]
			self.CM_x[min:max] = res_thr[np][1][:]
			self.CM_y[min:max] = res_thr[np][2][:]
			self.CM_z[min:max] = res_thr[np][3][:]

Hors ligne