IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

[parallel] Paralléliser une boucle for


Sujet :

Shell et commandes GNU

  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Par défaut [parallel] Paralléliser une boucle for
    Bonjour,
    je cherche à paralléliser les itérations du script suivant, tout en controlant le nombre de coeur utilisé par chaque itérations :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    #!/bin/bash
     
    ###################################
    ## Exploration of parameter space :
    ###################################
     
    Npoints=100
    per_min=30
    per_max=30
    alpha_min=0
    alpha_max=4
    ind=1 ### 0 if linear in lambda, and 1 if linear in k.
     
     
    ###### Generation of the lambda values
    TEXTE1=$(cat Lambda_vector_gene.m | grep "Lambda_min =")
    TEXTE2="Lambda_min = ""$per_min"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Lambda_vector_gene.m
    TEXTE1=$(cat Lambda_vector_gene.m | grep "Lambda_max =")
    TEXTE2="Lambda_max = ""$per_max"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Lambda_vector_gene.m
    TEXTE1=$(cat Lambda_vector_gene.m | grep "Ind =")
    TEXTE2="Ind = ""$ind"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Lambda_vector_gene.m
    matlab -nodesktop -nosplash -r Lambda_vector_gene
    TEXTE1=$(cat Lambda_vector_gene.m | grep "N =")
    TEXTE2="N = ""$Npoints"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Lambda_vector_gene.m
    matlab -nodesktop -nosplash -r Lambda_vector_gene
     
    echo "Lambda alpha Sigma Coeff" > sigma_values.data
    fichier="Lambda_vector.txt"
     
    #for ((L=$per_min; L<=$per_max; L+=2))
     
    ### Main Loop
    for L in $(<$fichier)
    do
    	for ((A=$alpha_min; A<=$alpha_max; A+=2))
    	do
    		echo "L = " "$L"
    		echo "A = " "$A"
    		dir="stability_L""$L""_A_""$A"
    		mkdir $dir
    		cp dun_stability.par run.bash exp_fit.m $dir
    		cp rescal/src/genesis rescal/src/rescal $dir
    		cd $dir	
     
    		### Run Rescal
    		TEXTE1=$(cat dun_stability.par | grep "Csp_template")
    		TEXTE2="Csp_template = WAVES_3D(""$L"",""$A"",4,30)"
    		sed -i "s/${TEXTE1}/${TEXTE2}/" dun_stability.par
    		./run.bash
     
     
    		### Run Matlab
     
    		TEXTE1=$(cat exp_fit.m | grep "Lambda =")
    		TEXTE2="Lambda = ""$L"
    		sed -i "s/${TEXTE1}/${TEXTE2}/" exp_fit.m
    		TEXTE1=$(cat exp_fit.m | grep "alpha =")
    		TEXTE2="alpha = ""$A"
    		sed -i "s/${TEXTE1}/${TEXTE2}/" exp_fit.m
    		matlab -nodesktop -nosplash -r exp_fit
     
    		### Preparation for data reading
    		head -n 1 sig_save.txt >> ../sigma_values.data
    		cd ../
     
    	done
     
    done
    La commande GNU parallel me parait assez approriée pour ça mais je n'ai pas réussit à comprendre comment m'en servir sur cet example. Etant donné que c'est une double boucle for, dont une des itérations lit la variable utile dans un fichier, ça faisait un peu trop de difficultés pour moi d'un coup. Pour l'instant, il me semble que je devrais écrire un script prenant en variable d'imput L et A, et ensuite entrer une commande du style
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    parallel -p ./mon script {1} {1..N}
    .

    Merci de votre aide !

  2. #2
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 636
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 636
    Par défaut
    Bonjour,

    il me semble que tout le script n'a pas à être parallélisé, et que seule la boucle doive l'être.
    je te suggère d'en faire une fonction, et de l'appeler avec parallel dans le script, tel que c'est montré dans cet exemple.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  3. #3
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Par défaut
    Merci de ta réponse, cet exemple est très parlant. J'ai 1/2 petites questions :

    1) si j'ai bien compris, quand je définis ma fonction, $1 (et resp. $1 et $2) correspondent aux indices de mes boucles for ?
    2) dans le double itération, $1 varie de 1 à 3 et $2 prend les valeurs A et B

    Je vais essayer ça, et je te dis ce que ça donne.
    Question subsidaire : la seule manière que je vois d'appliquer ça à mon problème, étant donné le , serait de faire varier une itération du parallel de 1 à nbre de ligne du fichier, et dans ma fonction de lire seulement la ligne i de ce fichier.

    Je me complique la vie et il y a plus simple, et ou c'est bon ?

    Merci encore !

    EDIT : Voici où j'en suis maintenant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    #!/bin/bash
     
    ###################################
    ## Exploration of parameter space :
    ###################################
     
    per_min=30
    per_max=32
    Npoints_L=3
    alpha_min=0
    alpha_max=0
    Npoints_A=1
    ind=1 ### 0 if linear in lambda, and 1 if linear in k.
     
     
    #### Cores definition
    Nc_available=4 #total nbr of core available
    Nc_each=1 #Nbr of core allocated for one iteration
    Njob=$(($Nc_available/$Nc_each))
     
    ###### Generation of the lambda and alpha vectors
    TEXTE1=$(cat Vector_gene.m | grep "Lambda_min =")
    TEXTE2="Lambda_min = ""$per_min"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
    TEXTE1=$(cat Vector_gene.m | grep "Lambda_max =")
    TEXTE2="Lambda_max = ""$per_max"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
    TEXTE1=$(cat Vector_gene.m | grep "Ind =")
    TEXTE2="Ind = ""$ind"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
    TEXTE1=$(cat Vector_gene.m | grep "N_L =")
    TEXTE2="N_L = ""$Npoints_L"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
     
    TEXTE1=$(cat Vector_gene.m | grep "Alpha_min =")
    TEXTE2="Alpha_min = ""$alpha_min"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
    TEXTE1=$(cat Vector_gene.m | grep "Alpha_max =")
    TEXTE2="Alpha_max = ""$alpha_max"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
    TEXTE1=$(cat Vector_gene.m | grep "N_A =")
    TEXTE2="N_A = ""$Npoints_A"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
     
     
     
     
    matlab -nodesktop -nosplash -r Vector_gene
     
    echo "Lambda alpha Sigma Coeff" > sigma_values.data
    fichier_L="Lambda_vector.txt"
    fichier_A="Alpha_vector.txt"
    dos2unix $fichier_L
    dos2unix $fichier_A
     
    #Definition of the function = One iteration
    Growth_rate() {
    		echo $1
    		echo $2
    		L=$(head -$1 $fichier_L | tail -1)
    		A=$(head -$2 $fichier_A | tail -1)
    		echo "L = ""$L"
    		echo "A = " "$A"
    		dir="stability_L""$L""_A_""$A"
    		mkdir $dir
    		cp dun_stability.par run.bash exp_fit.m $dir
    		cp rescal/src/genesis rescal/src/rescal $dir
    		cd $dir	
     
    		### Run Rescal
    		TEXTE1=$(cat dun_stability.par | grep "Csp_template")
    		TEXTE2="Csp_template = WAVES_3D(""$L"",""$A"",4,30)"
    		sed -i "s/${TEXTE1}/${TEXTE2}/" dun_stability.par
    		./run.bash
     
     
    		### Run Matlab
     
    		TEXTE1=$(cat exp_fit.m | grep "Lambda =")
    		TEXTE2="Lambda = ""$L"
    		sed -i "s/${TEXTE1}/${TEXTE2}/" exp_fit.m
    		TEXTE1=$(cat exp_fit.m | grep "alpha =")
    		TEXTE2="alpha = ""$A"
    		sed -i "s/${TEXTE1}/${TEXTE2}/" exp_fit.m
    		matlab -nodesktop -nosplash -r exp_fit
     
    		### Preparation for data reading
    		head -n 1 sig_save.txt >> ../sigma_values.data
    		cd ../
     
    		}
    export -f Growth_rate
     
    ### Main Loop
     
    #parallel --jobs $Njobs Growth_rate ::: $(seq $Npoints_L) ::: $(seq $Npoints_A)
    parallel Growth_rate ::: $(seq $Npoints_L) ::: $(seq $Npoints_A)
    J'ai quelques problèmes :
    1) si j'execute la commande en spécifiant le nombre de jobs, j'obtiens l'erreur "parallel: Error: Parsing of --jobs/-j/--max-procs/-P failed."
    2) si je l'enlève, le code semble tourner (avec une seule itération à la fois :/), maisles commandes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		L=$(head -$1 $fichier_L | tail -1)
    		A=$(head -$2 $fichier_A | tail -1)
    ne fonctionnent pas : L et A restent vide, alors que le fichiers d'input.txt sont bons.

  4. #4
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 636
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 636
    Par défaut
    exporte aussi les variables "$fichier_A" et "$fichier_L"
    ?

    en passant, tu peux remplacer tous les :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    TEXTE1=$(cat Vector_gene.m | grep "Lambda_min =")
    TEXTE2="Lambda_min = ""$per_min"
    sed -i "s/${TEXTE1}/${TEXTE2}/" Vector_gene.m
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed -i 's/Lambda_min = /&'"$per_min"'/' Vector_gene.m
    avec un tableau associatif, tu pourrais aussi "factoriser" avec une boucle for...
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  5. #5
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Par défaut
    Qu'entends-tu par : "exporte aussi les variables "$fichier_A" et "$fichier_L" ? " ?

    Je vais modifier le reste et utiliser un tableau associatif pour le début, ce sera plus propre. Mais le plus important est que j'arriver à utiliser cette commande parallel pour pouvoir faire tourner ce code sans que ça me prenne 10 jours ...

    Merci de ton aide !

  6. #6
    Modérateur
    Avatar de N_BaH
    Profil pro
    Inscrit en
    Février 2008
    Messages
    7 636
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 7 636
    Par défaut
    Qu'entends-tu par : "exporte aussi les variables "$fichier_A" et "$fichier_L" ? " ?
    de la même manière que parallel ne connaît pas la fonction si elle n'est pas exportée, la fonction qui est exécutée par parallel, puisque parallel ne les connaît pas, ne connaît pas les variables qu'elle utilise; il faut donc les exporter aussi.
    .
    N'oubliez pas de consulter les cours shell, la FAQ, et les pages man.

  7. #7
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Par défaut
    Oh, j'ai compris.
    Une idée sur ma syntaxe précisant le nombre de jobs qui doivent tourner en parallèles, et qui me renvoie une erreur ? (CF post 2)

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 814
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 814
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Liris Voir le message
    Une idée sur ma syntaxe précisant le nombre de jobs qui doivent tourner en parallèles, et qui me renvoie une erreur ? (CF post 2)
    Bonjour

    Chez-moi j'ai tenté un ls -d po* |parallel -P5 "tar cf - {} |xz -9 >{}.tar.xz" pour créer des archives "xz" à partir des dossiers commençant par "po" et ça a fonctionné (j'ai vu les ".tar.xz" arriver 5 par 5). Donc à priori l'option "-Pn" fonctionne.
    Mais au lieu de t'embêter à calculer un "Njob", pourquoi ne pas utiliser parallel -P0 ... qui demande que la parallélisation se fasse automatiquement sur le max de jobs possibles ???
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2016
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2016
    Messages : 11
    Par défaut
    Je vais re-tester des choses lundi, mais en bref, si tu regardes les instructions de la boucle for, les premières sont peu gourmandes, tandis que le .\run lance un modèle tournant sur 8 coeurs. J'ai peur qu'il lance beaucoup trop de jobs en parallèle au début, puis qu'ensuite ils attendent et se marchent dessus ?

    EDIT : Tout marche parfaitement, une erreur stupide (vraible définie en tant que Njob et pas Njobs ....) Merci à vous deux !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 04/07/2011, 16h56
  2. : remplir des zones de texte avec une boucle For
    Par Haro_GSD dans le forum Access
    Réponses: 3
    Dernier message: 20/09/2005, 21h23
  3. Problème avec une DLL dans une boucle For
    Par BraDim dans le forum Langage
    Réponses: 5
    Dernier message: 20/09/2005, 12h22
  4. [batch] incrémentation dans une boucle for
    Par bart64 dans le forum Scripts/Batch
    Réponses: 4
    Dernier message: 08/09/2004, 20h05
  5. Réponses: 3
    Dernier message: 06/07/2004, 10h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo