2017-09-26 3 views
0

Je suis relativement nouveau à Julia et j'ai quelques problèmes en essayant de paralléliser. J'ai essayé les deux approches pmap et @parallel et je rencontre le même problème. Quand je lance quelque chose comme:enveloppé code parallèle manière plus lente que non-emballé

addprocs(7) 
A0=zeros(a_size, b_size, c_size) 
A=SharedArray{Float64}(a_size,b_size,c_size) 
toler=1e-3 
maxit=1000 
while (metric1>toler) && (iter1<maxit) 
`@inbounds` `@sync` `@parallel` for i in 1:c_size 
A[:,:,i]=compute_A(fs,A0[:,:,i],i) 
end 
A_new=sdata(A) 
metric1=maximum(abs.((A_new-A0))) 
A0=copy(A_new) 
iter1=iter1+1 
println("$(iter1) $(metric1)") 
end 

où les entrées de la fonction compute_A sont:

  • fs est DataType défini par moi
  • A0 est un tableau
  • i est l'indice I 'm boucle sur (dimension c_size)

cela semble fonctionner très bien (même si au lieu de tableaux partagés et boucle @parallel J'utilise pmap)

Cependant, lorsque j'utilise une enveloppe en fonction de ce code, comme:

wrap(fs::DataType, toler::Float64, maxit::Int) 
A0=zeros(a_size, b_size, c_size) 
A=SharedArray{Float64}(a_size,b_size,c_size) 

    while (metric1>toler) && (iter1<maxit) 
`@inbounds` `@sync` `@parallel` for i in 1:c_size 
    A[:,:,i]=compute_A(fs,A0[:,:,i],i) 
end 
A_new=sdata(A) 
metric1=maximum(abs.((A_new-A0))) 
A0=copy(A_new) 
iter1=iter1+1 
println("$(iter1) $(metric1)") 
end 
end 

appel cette fonction wrap(fs, 1e-3, 1000) fonctionne WAY SLOWER que l'autre (comme 6 vs 600 secondes). Cela semble extrêmement bizarre et je ne comprends pas ce que je fais de mal, mais il y a définitivement quelque chose qui me manque, alors j'espérais pouvoir obtenir de l'aide ici. J'utilise Julia v0.6.0. Merci beaucoup pour votre temps et votre aide.

Répondre

0

Ma supposition (sans possibilité d'exécuter le code en question, c'est vraiment une supposition) est A0 n'est pas un SharedArray, et lorsqu'il est défini globalement, il est effectivement défini dans tous les processeurs, donc aucune communication n'est nécessaire pour cela (avez-vous remarqué A0 est une constante dans votre calcul?).

Dans la version enveloppée, elle est définie localement dans un processus et communiquée en permanence à d'autres processus. D'où les plus longs temps de fonctionnement.

Il est préférable d'avoir une localisation maximale des données. Si vous définissez A0 comme SharedArray de zéros en utilisant:

A0 = SharedArray{Float64,3}(a_size,b_size,c_size, 
          init = S -> S[Base.localindexes(S)] .= 0) 

dans les deux versions emballées et non emballés. En outre, conserver chaque tranche [:,:,i] sur un processeur serait idéal (en ayant nworkers() diviser c_size). REMARQUE: Je ne suis pas sûr du type d'édition qui s'est passé avant de mettre le code dans la question, mais si A0 est vraiment un tenseur zéro constant, il pourrait y avoir de meilleurs moyens de refactoriser le code. Si A0 est un autre tenseur, essayez:

A0 = SharedArray(otherTensor) 

une référence pertinente est SharedArray documentation qui détaille aussi comment mieux diviser un tenseur SharedArray 3D entre les processeurs, donc tranches restent à l'intérieur d'un processus pour une performance bien meilleure.

+0

Merci @DanGetz! Mais juste une clarification parce que je suis encore un peu confus avec l'informatique parallèle. Donc, fondamentalement, toutes les entrées qui vont dans la fonction qui sera calculée en parallèle doivent être définies comme des tableaux partagés si les tableaux et '@everywhere 'sont des constantes?Merci pour l'aide! –