/*************************************************************************************************************************************/ /* */ /* G E S T I O N " I N T E R N E " D U P A R A L L E L I S M E : */ /* */ /* */ /* Author of '$xcg/parallele.1N$K' : */ /* */ /* Jean-Francois COLONNA (LACTAMME, 20090414184411). */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* I N T E R F A C E ' listG ' : */ /* */ /* */ /* :Debut_listG: */ /* :Fin_listG: */ /* */ /*************************************************************************************************************************************/ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* D I R E C T I V E S S P E C I F I Q U E S D E C O M P I L A T I O N : */ /* */ /*************************************************************************************************************************************/ @define PRAGMA_CL_____PAS_DE_LIBRAIRIES_DYNAMIQUES /* Plus prudent, a cause de 'v $xcg/FindExec.01$Z .xcg.parallele.1..X'... */ @define PRAGMA_CL_____PAS_DE_FICHIER_____PARAM /* Introduit le 20170416092947 a cause de l'argument 'nombre_de_processus_parallelisables' */ /* qui est local a chaque MACHINE ('v $xcg/parallele.14$I ProcessorNumber')... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* F I C H I E R S D ' I N C L U D E S : */ /* */ /*************************************************************************************************************************************/ #include INCLUDES_MINI /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* P A R A M E T R E S : */ /* */ /*===================================================================================================================================*/ #include xcg/parallele.14.I" #define COMPATIBILITE_20120114 \ VRAI \ /* Permet de se placer dans l'etat anterieur a l'introduction des 'PRIORITE_DES_COMMANDES'. */ /* On notera que c'est l'etat par defaut et ceci a cause du fait qu'il y a de grosses */ /* differences entre 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH_DE_BASE' et */ /* 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH' en ce qui concerne la disponibilite de 'nice', le */ /* comportement vis a vis des parentheses ou encore des quotes. Or cette commande est tres */ /* utilisee par exemple dans 'execRVB' ou encore dans 'v $xcg/FindExec.01$Z PPaRaLlElE'. */ /* Donc pour ne pas perturber tout cela, retour avant le 20120114181453... */ #define BLOQUER_LE_PARALLELISME \ FAUX \ /* La possibilite d'inhiber le parallelisme directement a ete introduite le 20100630192050 */ \ /* pour 'v $Falias_execALBUM parallelisme='. Le 20100701095323, la logique de cet indicateur */ \ /* a ete inversee en passant de 'AUTORISER_LE_PARALLELISME' a 'BLOQUER_LE_PARALLELISME'... */ #define AJUSTER_AUTOMATIQUEMENT_PCMemorySizeMB \ VRAI \ /* La variable d'environnement '$PCMemorySizeMB' sera par defaut reduite proportionnellement */ \ /* a 'nombre_de_processus_parallelisables' (introduit le 20120214104603). */ #define COMPATIBILITE_PARALLELE_14 \ VRAI \ /* La possibilite d'inhiber la compatibilite avec 'v $xcg/parallele.14$K' a ete introduite */ \ /* le 20090416105323... */ #define EN_MODE_COMPATIBILITE_PARALLELE_14_AVERTIR_S_IL_Y_A_TROP_DE_PROCESS \ VRAI \ /* La possibilite d'inhiber le message correspondant a ete introduite le 20100412134427... */ #define DUPLIQUER_N_FOIS_LA_COMMANDE \ VRAI \ /* Faut-il dupliquer la commande autant de fois qu'il y a de processus paralleles possibles */ \ /* ('VRAI') ou pas ('FAUX') ? Cela fut introduit le 20140418122211. On notera qu'avant cette */ \ /* date, tout se passait comme si cette option (absente alors) etait 'VRAI'. La valeur par */ \ /* defaut est devenue 'VRAI' le 20140419102659 afin d'assurer la compatibilite avec les tres */ \ /* nombreux usages du type 'v $xiac/$Fnota .xcs.Linda.vv.Z''... */ #define EXECUTER_LES_COMMANDES_SOUS_CSH \ FAUX \ /* La possibilite d'executer les commandes sous '$CSH' a ete introduite le 20091021093824, */ \ /* la valeur par defaut assurant la compatibilite anterieure... */ #define PREMIER_NUMERO \ UN #define NOMBRE_DE_CHIFFRES_A_EDITER \ QUATRE /* Nombre de chiffres a editer pour les numeros (introduit le 20111116210724). */ #define CARACTERE_DE_SEPARATION_DES_COMMANDES \ K_DIESE \ /* Caractere de separation des commandes a paralleliser. */ \ /* */ \ /* Le 20090415081248, 'K_POINT_VIRGULE' fut remplace par 'K_DIESE' a fin de faciliter */ \ /* l'usage de chaines de commandes separees par des ";"s et parallelisables... */ #define EDITER_LES_COMMANDES_AVANT_LEUR_LANCEMENT \ FAUX \ /* Afin de permettre d'editer les commandes au lancement (introduit le 20120114184627)... */ #define QUOTE_DES_COMMANDES \ C_QUOTE \ /* Afin de pouvoir encadrer les commandes (introduit le 20120114190709)... */ \ /* */ \ /* Le 20120115111544 'C_VIDE' a ete remplace par 'C_QUOTE' a cause de "parentheser=VRAI" */ \ /* qui est utilise, par exemple, dans l'alias 'execRVB'. Or de toute evidence '$SH' utilise */ \ /* a partir de cette date dans 'v $xil/defi_c1$vv$DEF LANCEMENT_D_UNE_COMMANDE_SOUS_SH' */ \ /* ne tolere pas les parentheses si elles ne sont pas quotees... */ #define PRIORITE_DES_COMMANDES \ ZERO \ /* Priorite d'ordonnancement ("scheduling") des commandes (introduite le 20120114181453)... */ #define TEMPORISATION_APRES_CHAQUE_LANCEMENT \ ZERO \ /* La possibilite de temporiser apres chaque lancement d'une tache parallele a ete */ \ /* introduite le 20100122142622 afin de permettre d'eviter de saturer une MACHINE par */ \ /* le lancement simultane d'activites tres lourdes. */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* M A C R O S U T I L E S : */ /* */ /*************************************************************************************************************************************/ #define PREMIER_PROCESS \ INDEX0 #define INITIALISATION_COMMANDE(commande) \ Bblock \ INCR(nombre_de_commandes_initialisees,I); \ \ Test(IFLE(nombre_de_commandes_initialisees,nombre_de_processus_parallelisables)) \ Bblock \ EGAL(commande,chain_Acopie(commande_unique_a_paralleliser)); \ Eblock \ ATes \ Bblock \ Eblock \ ETes \ Eblock \ /* Introduit le 20090415081717 afin de disposer d'un mode compatible avec la commande */ \ /* 'v $xcg/parallele.14$K'. */ #define _____UN \ UN #define ___DEUX \ DEUX #define __TROIS \ TROIS #define _QUATRE \ QUATRE /* Afin d'ameliorer les tabulations... */ #define GENERE_COMMANDE__(commande,numero) \ COND(IFNE_chaine(commande,C_VIDE) \ ,chain_Aconcaten2(commande \ ,COND(IFNE_chaine(racine_des_fichiers_de_redirection,C_VIDE) \ ,chain_Aconcaten5(C_BLANC \ ,COND(IL_FAUT(executer_les_commandes_sous_CSH) \ ,C_CSH__REDIRECTION_FICHIER \ ,C_SH__REDIRECTION_FICHIER \ ) \ ,C_BLANC \ ,racine_des_fichiers_de_redirection \ ,chain_numero(numero,nombre_de_chiffres_a_editer) \ ) \ ,ccCHAR(C_VIDE) \ ) \ ) \ ,ccCHAR(C_VIDE) \ ) #define GENERE_SEPARATEUR(commande) \ COND(IFNE_chaine(commande,C_VIDE),chaine_separateur,ccCHAR(C_VIDE)) /* Procedures introduites le 20090416094310 afin d'alleger la generation de la liste */ /* 'liste_des_commandes'... */ /* */ /* On notera que 'chaine_separateur' n'est pas insere lorsque la 'commande??' qui precede */ /* est vide ('v $xcg/parallele.1N$K 20090415114639') afin de maximiser le parallelisme... */ #define IL_N_Y_A_AUCUNE_COMMANDE_DE_TYPE_parallele_14 \ IFET(IFEQ_chaine(commande_unique_a_paralleliser,C_VIDE) \ ,I4ET(IFEQ_chaine(commande11,C_VIDE) \ ,IFEQ_chaine(commande12,C_VIDE) \ ,IFEQ_chaine(commande21,C_VIDE) \ ,IFEQ_chaine(commande22,C_VIDE) \ ) \ ) \ /* Introduit le 20090416135000 afin de simplifier les validations ulterieures, puis */ \ /* passage d'un 'Logical' a un '#define' le 20090417210844... */ #define COMMANDE_PARALLELE_COURANTE \ COND(IL_FAUT(compatibilite_20120114) \ ,chain_Aconcaten2(COND(IL_FAUT(executer_les_commandes_sous_CSH) \ ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_CSH) \ ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_SH_DE_BASE) \ ) \ ,ITb1(commande_courante,INDX(numero_des_process,PREMIER_PROCESS)) \ ) \ ,chain_Aconcaten5(COND(IL_FAUT(executer_les_commandes_sous_CSH) \ ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_CSH) \ ,ccCHAR(LANCEMENT_D_UNE_COMMANDE_SOUS_SH) \ ) \ ,quote_des_commandes \ ,COND(IZEQ(priorite_des_commandes) \ ,ccCHAR(C_VIDE) \ ,chain_Aconcaten3(COND(IL_FAUT(executer_les_commandes_sous_CSH) \ ,ccCHAR(CHANGEMENT_DE_PRIORITE_D_UNE_COMMANDE_SOUS_CSH) \ ,ccCHAR(CHANGEMENT_DE_PRIORITE_D_UNE_COMMANDE_SOUS_SH) \ ) \ ,chain_Aentier(priorite_des_commandes) \ ,C_BLANC \ ) \ ) \ ,ITb1(commande_courante,INDX(numero_des_process,PREMIER_PROCESS)) \ ,quote_des_commandes \ ) \ ) \ /* Commande parallele courante (introduite le 20120114184627... */ /*===================================================================================================================================*/ /*************************************************************************************************************************************/ /* */ /* G E S T I O N " I N T E R N E " D U P A R A L L E L I S M E : */ /* */ /*************************************************************************************************************************************/ BCommande(nombre_d_arguments,arguments) /*-----------------------------------------------------------------------------------------------------------------------------------*/ Bblock DEFV(Logical,INIT(compatibilite_20120114,COMPATIBILITE_20120114)); /* Permet de se placer dans l'etat anterieur a l'introduction des 'priorite_des_commandes'. */ /* On notera que c'est l'etat par defaut et ceci a cause du fait qu'il y a de grosses */ /* differences entre 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH_DE_BASE' et */ /* 'LANCEMENT_D_UNE_COMMANDE_SOUS_SH' en ce qui concerne la disponibilite de 'nice', le */ /* comportement vis a vis des parentheses ou encore des quotes. Or cette commande est tres */ /* utilisee par exemple dans 'execRVB' ou encore dans 'v $xcg/FindExec.01$Z PPaRaLlElE'. */ /* Donc pour ne pas perturber tout cela, retour avant le 20120114181453... */ DEFV(Logical,INIT(bloquer_le_parallelisme,BLOQUER_LE_PARALLELISME)); /* La possibilite d'inhiber le parallelisme directement a ete introduite le 20100630192050 */ /* pour 'v $Falias_execALBUM parallelisme='. Le 20100701095323, la logique de cet indicateur */ /* a ete inversee en passant de 'autoriser_le_parallelisme' a 'bloquer_le_parallelisme'... */ DEFV(Logical,INIT(ajuster_automatiquement_PCMemorySizeMB,AJUSTER_AUTOMATIQUEMENT_PCMemorySizeMB)); /* La variable d'environnement '$PCMemorySizeMB' sera par defaut reduite proportionnellement */ /* a 'nombre_de_processus_parallelisables' (introduit le 20120214104603). */ DEFV(Logical,INIT(compatibilite_parallele_14,COMPATIBILITE_PARALLELE_14)); /* La possibilite d'inhiber la compatibilite avec 'v $xcg/parallele.14$K' a ete introduite */ /* le 20090416105323... */ DEFV(Logical,INIT(en_mode_compatibilite_parallele_14_avertir_s_il_y_a_trop_de_process ,EN_MODE_COMPATIBILITE_PARALLELE_14_AVERTIR_S_IL_Y_A_TROP_DE_PROCESS ) ); /* La possibilite d'inhiber le message correspondant a ete introduite le 20100412134427... */ DEFV(Logical,INIT(dupliquer_N_fois_la_commande,DUPLIQUER_N_FOIS_LA_COMMANDE)); DEFV(Positive,INIT(nombre_de_duplications_de_la_commande,NOMBRE_DE_PROCESSUS_PARALLELISABLES)); /* Faut-il dupliquer la commande autant de fois qu'il y a de processus paralleles possibles */ /* ('VRAI') ou pas ('FAUX') ? Cela fut introduit le 20140418122211. On notera qu'avant cette */ /* date, tout se passait comme si cette option (absente alors) etait 'VRAI'. La valeur par */ /* defaut est devenue 'VRAI' le 20140419102659 afin d'assurer la compatibilite avec les tres */ /* nombreux usages du type 'v $xiac/$Fnota .xcs.Linda.vv.Z''... */ /* */ /* Ceci fut complete le 20140419111827 par le nombre de duplications... */ DEFV(CHAR,INIC(POINTERc(commande_unique_a_paralleliser),C_VIDE)); DEFV(CHAR,INIC(POINTERc(commande11),C_VIDE)); DEFV(CHAR,INIC(POINTERc(commande12),C_VIDE)); DEFV(CHAR,INIC(POINTERc(commande21),C_VIDE)); DEFV(CHAR,INIC(POINTERc(commande22),C_VIDE)); /* Introduit le 20090415081717 afin de disposer d'un mode compatible avec la commande */ /* 'v $xcg/parallele.14$K'. */ DEFV(CHAR,INIC(POINTERc(liste_des_commandes),C_VIDE)); /* Liste des commandes a paralleliser, sous la forme : */ /* */ /* COMMANDE1 # COMMANDE2 # (...) # COMMANDEi # (...) # COMMANDEn */ /* */ /* en supposant que 'caractere_de_separation_des_commandes' soit '#'. D'autre part, chaque */ /* 'COMMANDEi' peut etre de la forme : */ /* */ /* COMMANDEi1 ; COMMANDEi2 ; (...) ; COMMANDEij ; (...) ; COMMANDEim */ /* */ /* ou 'COMMANDEij' est une commande "simple" et les espaces ci-dessus etant purement */ /* "cosmetiques"... */ DEFV(CHAR,INIC(POINTERc(racine_des_fichiers_de_redirection),C_VIDE)); DEFV(Positive,INIT(premier_numero,PREMIER_NUMERO)); DEFV(Positive,INIT(nombre_de_chiffres_a_editer,NOMBRE_DE_CHIFFRES_A_EDITER)); /* Introduit le 20111116210724 afin de pouvoir eventuellement rediriger les sorties... */ DEFV(Logical,INIT(executer_les_commandes_sous_CSH,EXECUTER_LES_COMMANDES_SOUS_CSH)); /* La possibilite d'executer les commandes sous '$CSH' a ete introduite le 20091021093824, */ /* la valeur par defaut assurant la compatibilite anterieure... */ DEFV(CHAR,INIT(caractere_de_separation_des_commandes,CARACTERE_DE_SEPARATION_DES_COMMANDES)); /* Caractere de separation des commandes a paralleliser (voir le commentaire precedent...). */ DEFV(Positive,INIT(nombre_de_processus_parallelisables,NOMBRE_DE_PROCESSUS_PARALLELISABLES)); /* Nombre de processus parallelisables. */ /* */ /* On notera le 20090415132416 qu'en faisant : */ /* */ /* NombreProcessParalleles=1 */ /* */ /* on se place dans une situation equivalente au : */ /* */ /* parallelisme=FAUX */ /* */ /* de 'v $xcg/parallele.14$K, c'est-a-dire que l'on se met en mode "sequentiel"... */ DEFV(Logical,INIT(editer_les_commandes_avant_leur_lancement,EDITER_LES_COMMANDES_AVANT_LEUR_LANCEMENT)); /* Afin de permettre d'editer les commandes avant le lancement et dans un ordre qui n'est */ /* pas a priori l'ordre numerique 'numero_des_process' (introduit le 20120114184627)... */ DEFV(CHAR,INIC(POINTERc(quote_des_commandes),QUOTE_DES_COMMANDES)); /* Afin de pouvoir encadrer les commandes (introduit le 20120114190709)... */ DEFV(Positive,INIT(priorite_des_commandes,PRIORITE_DES_COMMANDES)); /* Priorite d'ordonnancement ("scheduling") des commandes (introduite le 20120114181453)... */ DEFV(Int,INIT(temporisation_apres_chaque_lancement,TEMPORISATION_APRES_CHAQUE_LANCEMENT)); /* La possibilite de temporiser apres chaque lancement d'une tache parallele a ete */ /* introduite le 20100122142622 afin de permettre d'eviter de saturer une MACHINE par */ /* le lancement simultane d'activites tres lourdes. */ DEFV(Int,INIT(index_du_premier_caractere_de_la_commande_courante,PREMIER_CARACTERE)); DEFV(Logical,INIT(toutes_les_commandes_ont_ete_recuperees,FAUX)); /* Afin de recuperer toutes les commandes a paralleliser... */ /*..............................................................................................................................*/ GET_ARGUMENTS_(nombre_d_arguments ,BLOC(GET_ARGUMENT_L("compatibilite_20120114=",compatibilite_20120114); GET_ARGUMENT_L("sequentiel=""seq=",bloquer_le_parallelisme); GET_ARGUMENT_N("parallelisme=""parallele=""para=",bloquer_le_parallelisme); /* Argument introduit le 20100630192050. Le 20100701095323, la logique de cet indicateur */ /* a ete inversee en passant de 'autoriser_le_parallelisme' a 'bloquer_le_parallelisme'... */ GET_ARGUMENT_L("PCMemorySizeMB=""PCM=",ajuster_automatiquement_PCMemorySizeMB); /* Arguments introduits le 20120214104603... */ GET_ARGUMENT_L("compatibilite_parallele_14=""parallele_14=""p14=",compatibilite_parallele_14); GET_ARGUMENT_L("avertir_trop_de_process_compatibilite_parallele_14=""atp=" ,en_mode_compatibilite_parallele_14_avertir_s_il_y_a_trop_de_process ); /* Arguments introduits le 20100412134427... */ GET_ARGUMENT_L("dupliquer_N_fois=""dupliquer=""dup=",dupliquer_N_fois_la_commande); GET_ARGUMENT_I("nombre_duplications=""duplications=""ndup=",nombre_de_duplications_de_la_commande); /* Arguments introduits le 20140418122211 et completes le 20140419111827... */ GET_ARGUMENT_C("commande=""cm=""c=""C=",commande_unique_a_paralleliser); GET_ARGUMENT_C("commande1=""commande11=""cm1=""c1=""c11=""C1=""C11=",commande11); GET_ARGUMENT_C("commande2=""commande12=""cm2=""c2=""c12=""C2=""C12=",commande12); GET_ARGUMENT_C("commande3=""commande21=""cm3=""c3=""c21=""C3=""C21=",commande21); GET_ARGUMENT_C("commande4=""commande22=""cm4=""c4=""c22=""C4=""C22=",commande22); /* Le 20090415111836, je note que les cinq 'GET_ARGUMENT_C(...)'s qui precedent doivent etre */ /* identiques a ceux de 'v $xcg/parallele.14$K GET_ARGUMENT_C' pour assurer la compatibilite */ /* de 'v $xcg/parallele.1N$K' et de 'v $xcg/parallele.14$K'. */ GET_ARGUMENT_C("liste_commandes=""lc=""liste=""commandes=""cms=""cs=""Cs=",liste_des_commandes); GET_ARGUMENT_C("fichiers_redirection=""redirection=""fr=",racine_des_fichiers_de_redirection); GET_ARGUMENT_I("chiffres=",nombre_de_chiffres_a_editer); GET_ARGUMENT_I("premier_numero=""premier=""p=",premier_numero); /* Arguments introduits le 20111116210724... */ GET_ARGUMENT_L("CSH=""csh=",executer_les_commandes_sous_CSH); GET_ARGUMENT_N("SH=""sh=",executer_les_commandes_sous_CSH); GET_ARGUMENT_K("separateur=""sep=",caractere_de_separation_des_commandes); GET_ARGUMENT_I("NombreProcessParalleles=""process=""processus=""np=""nombre=""NP=" ,nombre_de_processus_parallelisables ); GET_ARGUMENT_L("editer_commandes=""ec=",editer_les_commandes_avant_leur_lancement); /* Arguments introduits le 20120114184627... */ PROCESS_ARGUMENT_C("quotes=""q=",quote_des_commandes ,BLOC(VIDE;) ,BLOC(Test(IFGT(chain_Xtaille(quote_des_commandes),size_CHAR)) Bblock PRINT_ATTENTION("la 'quote' des commandes est a priori un caractere unique"); Eblock ATes Bblock Eblock ETes ) ); /* Arguments introduits le 20120114190709... */ GET_ARGUMENT_I("temporisation=""tempo=",temporisation_apres_chaque_lancement); /* Arguments introduits le 20100122142622... */ GET_ARGUMENT_I("priorite_commandes=""priorite=""nice=",priorite_des_commandes); /* Arguments introduits le 20100122142622... */ ) ); Test(IL_FAUT(compatibilite_20120114)) /* Test introduit le 20120115120709... */ Bblock Eblock ATes Bblock Test(IFET(IZGT(priorite_des_commandes) ,IFET(IFNE_chaine(quote_des_commandes,C_APOSTROPHE) ,IFNE_chaine(quote_des_commandes,C_QUOTE) ) ) ) /* Test introduit le 20120114192311... */ Bblock PRINT_ATTENTION("il est preferable de 'quoter' les commandes non prioritaires"); Eblock ATes Bblock Eblock ETes Eblock ETes begin_nouveau_block Bblock DEFV(CHAR,INIS(DTb0(chaine_separateur),Ichaine01(caractere_de_separation_des_commandes))); /* ATTENTION : c'est 'INIS(...)' qui est utilise (et non pas 'INIT(...)') afin de ne pas */ /* parentheser la liste 'Ichaine01(...)'. */ Test(IL_FAUT(bloquer_le_parallelisme)) /* Test introduit le 20100630192050. Le 20100701095323, la logique de cet indicateur */ /* a ete inversee en passant de 'autoriser_le_parallelisme' a 'bloquer_le_parallelisme'... */ Bblock EGAL(nombre_de_processus_parallelisables,UN); /* Et voila comment bloquer le parallelisme... */ Eblock ATes Bblock Eblock ETes Test(IL_FAUT(compatibilite_parallele_14)) /* Test introduit le 20090416105323... */ Bblock Test(IFEQ_chaine(liste_des_commandes,C_VIDE)) /* Lorsque la liste des commandes est vide, cela declenche le mode de compatibilite avec */ /* '$xcg/parallele.14$K'. Les commandes individuelles vont etre concatenees (si elles */ /* existent afin de donner naissance a la liste...). */ Bblock Test(IFGT(nombre_de_processus_parallelisables,NOMBRE_DE_PROCESSUS_PARALLELISABLES_4)) Bblock Test(EST_VRAI(en_mode_compatibilite_parallele_14_avertir_s_il_y_a_trop_de_process)) /* Test introduit le 20100412134427... */ Bblock PRINT_ATTENTION("en mode compatible '$xcg/parallele.14$K' le nombre de process paralleles est limite"); CAL1(Prer2("(%d process etaient demandes alors que %d seront utilises au maximum)\n" ,nombre_de_processus_parallelisables ,NOMBRE_DE_PROCESSUS_PARALLELISABLES_4 ) ); Eblock ATes Bblock Eblock ETes EGAL(nombre_de_processus_parallelisables,NOMBRE_DE_PROCESSUS_PARALLELISABLES_4); /* Limitation introduite le 20090415123925... */ Eblock ATes Bblock Eblock ETes Test(IFNE_chaine(commande_unique_a_paralleliser,C_VIDE)) Bblock Test(I4ET(IFEQ_chaine(commande11,C_VIDE) ,IFEQ_chaine(commande12,C_VIDE) ,IFEQ_chaine(commande21,C_VIDE) ,IFEQ_chaine(commande22,C_VIDE) ) ) Bblock DEFV(Int,INIT(nombre_de_commandes_initialisees,ZERO)); INITIALISATION_COMMANDE(commande11); INITIALISATION_COMMANDE(commande12); INITIALISATION_COMMANDE(commande21); INITIALISATION_COMMANDE(commande22); Eblock ATes Bblock PRINT_ATTENTION("la 'commande unique' est ignoree, l'une au moins des quatre commandes etant definie"); CAL1(Prer1("(elle etait '%s')\n",commande_unique_a_paralleliser)); Eblock ETes Eblock ATes Bblock Eblock ETes EGAL(liste_des_commandes ,chain_Aconcaten7(GENERE_COMMANDE__(commande11,_____UN),GENERE_SEPARATEUR(commande11) ,GENERE_COMMANDE__(commande12,___DEUX),GENERE_SEPARATEUR(commande12) ,GENERE_COMMANDE__(commande21,__TROIS),GENERE_SEPARATEUR(commande21) ,GENERE_COMMANDE__(commande22,_QUATRE) ) ); Eblock ATes Bblock Test(EST_FAUX(IL_N_Y_A_AUCUNE_COMMANDE_DE_TYPE_parallele_14)) Bblock PRINT_ATTENTION("le mode compatible '$xcg/parallele.14$K' est bloque, une liste de commandes etant presente"); Eblock ATes Bblock Eblock ETes Eblock ETes Eblock ATes Bblock Test(EST_FAUX(IL_N_Y_A_AUCUNE_COMMANDE_DE_TYPE_parallele_14)) Bblock Test(IL_FAUT(dupliquer_N_fois_la_commande)) /* Test introduit le 20140418122211... */ Bblock DEFV(Int,INIT(numero_courant,premier_numero)); /* Numero courant eventuel du fichier de redirection... */ Repe(nombre_de_duplications_de_la_commande) Bblock EGAL(liste_des_commandes ,chain_Aconcaten2(liste_des_commandes,GENERE_COMMANDE__(commande_unique_a_paralleliser,numero_courant)) ); /* Cette possibilite a ete introduite le 20100329085302 afin de favoriser l'execution de */ /* 'v $xcs/Linda$vv$Z' (par exemple dans 'v $xiac/$Fnota .xcs.Linda.vv.Z'). */ Test(IFLT(compteur_des_repetitions_du_Repe,nombre_de_duplications_de_la_commande)) /* ATTENTION, jusqu'au 20200114143902, il y avait ici (par erreur ?) : */ /* */ /* Test(IFLT(compteur_des_repetitions_du_Repe,nombre_de_processus_parallelisables)) */ /* */ /* Cela s'est vu en introduisant l'alias 'v $xE/.alias.2$vv$y execPar_F'... */ Bblock EGAL(liste_des_commandes ,chain_Aconcaten2(liste_des_commandes,GENERE_SEPARATEUR(commande_unique_a_paralleliser)) ); Eblock ATes Bblock Eblock ETes INCR(numero_courant,I); /* Numero courant eventuel du fichier de redirection... */ Eblock ERep Eblock ATes Bblock EGAL(liste_des_commandes ,chain_Aconcaten2(liste_des_commandes,GENERE_COMMANDE__(commande_unique_a_paralleliser,premier_numero)) ); /* Introduit le 20140418122211 a cause de 'v $xcg/FindExec.01$Z LiMiTeUr' qui met toutes les */ /* commandes "bout a bout" seperees par le "#"... */ Eblock ETes Eblock ATes Bblock Eblock ETes Eblock ETes Eblock end_nouveau_block Test(IL_FAUT(ajuster_automatiquement_PCMemorySizeMB)) /* Test introduit le 20120214104603. */ Bblock Pval("PCMemorySizeMB" ,DIVI(sHOTE_____TAILLE_DE_LA_MEMOIRE_DE_REFERENCE_EN_MEGA_OCTETS,nombre_de_processus_parallelisables) ); /* Ainsi le pourcentage de la memoire physique a priori utilisable est partage equitablement */ /* entre tous les processus qui vont etre lances (introduit le 20120214104603). */ Eblock ATes Bblock Eblock ETes Tant(EST_FAUX(toutes_les_commandes_ont_ete_recuperees)) Bblock /* Bouclage sur l'integralite des commandes arguments : */ DEFV(CHAR,POINTERc(DTb1(commande_courante,nombre_de_processus_parallelisables))); /* Liste des commandes courantes parallelisees. */ DEFV(processus,DTb1(process_parallelises,nombre_de_processus_parallelisables)); /* Identificateur des process correspondant aux commandes courantes parallelisees. */ DEFV(Int,INIT(numero_des_process,PREMIER_PROCESS)); /* Index des differents process... */ Tant(IFET(IFLE(numero_des_process,LSTX(PREMIER_PROCESS,nombre_de_processus_parallelisables)) ,EST_FAUX(toutes_les_commandes_ont_ete_recuperees) ) ) /* Bouclage sur un "paquet" de 'nombre_de_processus_parallelisables' commandes arguments : */ Bblock BSaveModifyVariable(Int ,chain_copie_____index_du_premier_caractere_d_une_chaineA ,index_du_premier_caractere_de_la_commande_courante ); BSaveModifyVariable(CHAR ,chain_copie_____caractere_d_arret_secondaire ,caractere_de_separation_des_commandes ); BSaveModifyVariable(Logical ,chain_copie_____copier_le_caractere_d_arret_secondaire ,FAUX ); BSaveModifyVariable(Int ,chain_copie_____premier_index_de_test_du_caractere_d_arret_secondaire ,PREMIER_CARACTERE ); /* Afin de recuperer la commande courante dans la liste des commandes. */ EGAL(ITb1(commande_courante,INDX(numero_des_process,PREMIER_PROCESS)),chain_Acopie(liste_des_commandes)); /* Recuperation de la commande courante. */ /* */ /* On notera qu'il n'est en fait pas utile que 'commande_courante' soit un vecteur de */ /* chaines de caracteres. Il suffirait en fait de le definir par: */ /* */ /* DEFV(CHAR,POINTERc(commande_courante)); */ /* */ /* mais on ne sait jamais, peut-etre que plus tard... */ ESaveModifyVariable(Int,chain_copie_____premier_index_de_test_du_caractere_d_arret_secondaire); ESaveModifyVariable(Logical,chain_copie_____copier_le_caractere_d_arret_secondaire); ESaveModifyVariable(CHAR,chain_copie_____caractere_d_arret_secondaire); ESaveModifyVariable(Int,chain_copie_____index_du_premier_caractere_d_une_chaineA); /* Restaurations... */ iPARALLELE(BLOC( Bblock Test(IL_FAUT(editer_les_commandes_avant_leur_lancement)) Bblock CAL3(Prme3("Commande parallele %0*d='%s'\n" ,NOMBRE_DE_CHIFFRES_DECIMAUX(nombre_de_processus_parallelisables) ,numero_des_process ,COMMANDE_PARALLELE_COURANTE ) ); /* Possibilite introduite le 20120114184627... */ /* */ /* Le 20120115172535 fut introduit l'edition de 'numero_des_process'... */ /* */ /* On notera evidemment que les differentes commandes ne sortent pas necessairement dans */ /* l'ordre numerique de 'numero_des_process' a cause de 'iPARALLELE(...)' qui possede un */ /* fonctionnement asynchrone... */ Eblock ATes Bblock Eblock ETes CALS(SYSTEM(COMMANDE_PARALLELE_COURANTE)); Eblock ) ,ITb1(process_parallelises,INDX(numero_des_process,PREMIER_PROCESS)) ); /* Lancement en parallele de la commande courante. */ /* */ /* On notera le 20090415114639 le fonctionnement suivant : */ /* */ /* soit (par exemple...) : */ /* */ /* NombreProcessParalleles=2 */ /* */ /* Ensuite : */ /* */ /* liste_commandes="COMMANDE1#COMMANDE2" */ /* */ /* provoquera l'execution simultanee et parallele de 'COMMANDE1' et 'COMMANDE2', alors */ /* que : */ /* */ /* liste_commandes="COMMANDE1##COMMANDE2" */ /* _ */ /* provoquera l'execution simultanee et parallele de 'COMMANDE1' et d'une commande vide */ /* a cause du deuxieme '#'), puis ENSUITE de 'COMMANDE2'. C'est pour eviter cela que le */ /* separateur (via 'chaine_separateur') n'est pas insere si une commande vide le precede */ /* lors du mode compatible '$xcg/parallele.14$K'... */ /* */ /* Le 20091021093824 fut introduite la possibilite d'executer les commandes sous '$CSH', */ /* autorisant ainsi l'utilisation d'alias... */ DODO(temporisation_apres_chaque_lancement); /* Temporisation eventuelle introduite le 20100122142622... */ /* */ /* Celle-ci est destinee a permettre (si besoin est) d'eviter de saturer une MACHINE par */ /* le lancement simultane d'activites tres lourdes. C'est par exemple le cas avec : */ /* */ /* execRVB $xci/accumule.41$X ... */ /* */ /* dans 'v $xiirc/$Fnota execRVB....xci.accumule.41.X' qui provoquent la lecture simultanee */ /* de tres gros fichiers au demarrage... */ EGAL(index_du_premier_caractere_de_la_commande_courante ,chain_copie_____successeur_de_l_index_du_dernier_caractere_d_une_chaineA ); /* Pour preparer le 'chain_Acopie(...)' eventuel suivant... */ Test(EST_VRAI(chain_copie_____la_chaineA_a_ete_copiee_jusqu_au_END_OF_CHAIN)) Bblock EGAL(toutes_les_commandes_ont_ete_recuperees,VRAI); /* Toutes les commandes ont apparemment ete recuperees... */ Eblock ATes Bblock Eblock ETes INCR(numero_des_process,I); Eblock ETan Tant(IFGT(numero_des_process,PREMIER_PROCESS)) Bblock DECR(numero_des_process,I); WAIT(ITb1(process_parallelises,INDX(numero_des_process,PREMIER_PROCESS))); /* Attente de fin de toutes les commandes lancees en parallele. En fait, ainsi on */ /* attend celle dont l'execution est la plus longue... */ Eblock ETan Eblock ETan RETU_Commande; Eblock ECommande