Le cadre d'automatisation du raffinement des instruments de performance PIRA aborde la tâche fastidieuse consistant à générer une mesure de performance raisonnable pour une base de code inconnue lors de l'utilisation de Score-P. Pour plus d’informations, veuillez consulter nos articles :
[PI18] | Jan-Patrick Lehr, Alexander Hück, Christian Bischof. PIRA : automatisation du raffinement des instruments de performance. Dans le 5e atelier international ACM SIGPLAN sur l'intelligence artificielle et les méthodes empiriques pour le génie logiciel et les systèmes informatiques parallèles (AI-SEPS) , pages 1-10, ACM, 2018. |
[PI19] | Jan-Patrick Lehr, Alexandru Calotoiu, Christian Bischof, Felix Wolf. Raffinement automatique de l'instrumentation pour la modélisation empirique des performances. Dans Atelier international sur les outils de programmation et de visualisation des performances (ProTools) , pages 40-47, IEEE, 2019. |
[PI21] | Peter Arzt, Yannic Fischler, Jan-Patrick Lehr, Christian Bischof. Détection automatique de déséquilibre de charge à faible surcharge dans les applications MPI. Dans Euro-Par 2021 : Traitement parallèle. Notes de cours en informatique, vol 12820 , pages 19-34, Springer, 2021. |
PIRA exécute les quatre phases suivantes (2 à 4 sont itérées) :
PIRA prend en charge le filtrage des fonctions à la compilation et à l'exécution , y compris le filtrage à l'exécution des fonctions MPI via des wrappers générés automatiquement. Dans le filtrage au moment de la compilation, seules les fonctions souhaitées sont instrumentées au moment de la compilation, ce qui réduit considérablement l'influence globale de la mesure. En revanche, dans le filtrage à l'exécution, le compilateur insère des hooks d'instrumentation dans chaque fonction de l'application cible, et le filtrage a lieu au moment de l'exécution.
PIRA nécessite CMake (>=3.16), Clang/LLVM 10, Python 3, Qt5 et OpenMPI 4. Il (ou MetaCG) sera ensuite téléchargé (et construit)
Si vous souhaitez créer PIRA dans un environnement sans accès Internet, veuillez consulter le script resources/build_submodules.sh
et ajustez-le à vos besoins.
Clonez le référentiel PIRA.
$> git clone https://github.com/tudasc/pira
$> cd pira
Deuxièmement, créez les sous-modules dépendants à l'aide du script fourni ou transmettez les valeurs des différentes options (voir les informations d'utilisation via -h
pour les options disponibles). Tous les fichiers téléchargés et construits seront placés dans external/src/
tandis que toutes les installations seront placées dans external/install/
. Spécifiez le nombre de processus de compilation à générer pour la compilation des externes de PIRA. Le script téléchargera les dépendances de PIRA dans leur version par défaut. Ces versions sont également testées dans notre CI et devraient fonctionner.
$> cd resources
$> ./build_submodules.sh -p <ncores>
Comme étape finale, le script de construction écrira les chemins d'installation des sous-modules dans le fichier resources/setup_paths.sh
. Si vous souhaitez reconstruire PIRA, n'oubliez pas de git restore
ce fichier.
Nous fournissons également un Dockerfile
(expérimental) pour construire PIRA et l'essayer.
$> podman build -t pira:master -f docker/Dockerfile .
Lors de l'exécution à l'intérieur du conteneur, par exemple pour les tests d'intégration, veuillez appeler les scripts comme suit.
$> cd resources
$> . setup_paths.sh
$> cd ../test/integration/GameOfLife # Example test case
# By default PIRA will look into $HOME/.local, which is not currently existent in the docker
# XDG_DATA_HOME signals where to put the profiling data PIRA generates
$> XDG_DATA_HOME=/tmp ./run.sh
Pour un exemple complet d'utilisation de PIRA, consultez les scripts run.sh
dans le dossier /test/integration/*
. Un bon point de départ est le dossier GameOfLife
et son scénario de test.
Tout d’abord, configurez les chemins requis en recherchant le script dans le dossier resources
.
$> cd resources/
$> . setup_paths.sh
Ensuite, vous pouvez exécuter un exemple d'application de PIRA sur une implémentation très simple de Game of Life de Conway en utilisant le script run.sh
fourni dans le dossier ./test/integration/GameOfLife
.
$> cd ./test/integration/GameOfLife
$> ./run.sh
Le script exécute toutes les étapes requises dès le départ, c'est-à-dire prépare tous les composants pour un nouveau code cible, pour finalement appeler PIRA. Dans les sections suivantes, les étapes sont expliquées plus en détail. Les étapes sont les suivantes :
config
Chemin d'accès au fichier de configuration (argument obligatoire)--config-version [1,2]
Version de la configuration PIRA, 2 est la valeur par défaut et est encouragée ; 1 est obsolète.--runtime-filter
Utiliser le filtrage à l'exécution, la valeur par défaut est false. Dans le filtrage au moment de la compilation, les fonctions ne sont pas instrumentées au moment de la compilation, ce qui réduit considérablement l'influence globale de la mesure, mais nécessite la reconstruction de la cible à chaque itération. En revanche, avec le filtrage d'exécution, le compilateur insère des hooks d'instrumentation dans chaque fonction de l'application cible.--iterations [number]
Nombre d'itérations Pira, la valeur par défaut est 3.--repetitions [number]
Nombre de répétitions de mesure, la valeur par défaut est 3.--tape
Emplacement où une bande de journalisation (quelque peu étendue) doit être écrite.--extrap-dir
Le répertoire de base où est placée la structure de dossiers Extra-p.--extrap-prefix
Le préfixe Extra-P doit être une séquence de caractères.--version
Imprime le numéro de version de l'installation de PIRA--analysis-parameters
Chemin d'accès au fichier de configuration contenant les paramètres d'analyse pour PGIS. Requis pour les modes Extra-P et LIDe.--slurm-config [path to slurm cfg file]
Permet d'exécuter le code cible sur un cluster slurm. Un fichier de configuration Slurm est nécessaire. Veuillez consulter cette section pour plus d'informations. --hybrid-filter-iters [number]
Recompilez après [nombre] itérations, utilisez le filtrage d'exécution entre les deux.--export
Attache les modèles Extra-P générés et les tailles des ensembles de données dans le fichier IPCG de la cible.--export-runtime-only
Nécessite --export
; Attache uniquement la valeur d'exécution médiane de toutes les répétitions aux fonctions. Uniquement disponible lorsque vous n’utilisez pas Extra-P.--load-imbalance-detection [path to cfg file]
Active et configure le mode de détection de déséquilibre de charge. Veuillez lire cette section pour plus d'informations. PIRA utilise les informations du code source pour construire une instrumentation initiale et décider quelles fonctions ajouter à une instrumentation lors du raffinement itératif. Il fournit un outil de graphique d'appel basé sur Clang qui collecte toutes les informations requises et affiche les informations dans un fichier .json
. Vous pouvez trouver l'outil cgcollector
dans le sous-répertoire ./extern/src/metacg/cgcollector
. PIRA nécessite que le fichier callgraph soit au format de fichier MetaCG dans la version 2 (MetaCG v2).
Plus d'informations sur CGCollector et ses composants peuvent être trouvées dans la documentation MetaCG.
L'application de CGCollector se déroule généralement en deux étapes.
Au début, cgc
est invoqué sur chaque fichier source du projet. par exemple :
for f in $(find ./src -type f ( -iname "*.c" -o -iname "*.cpp" ) ); do
cgc --metacg-format-version=2 $f
done
Les fichiers .ipcg
créés à l'étape 1 sont ensuite fusionnés dans un fichier général à l'aide de cgmerge
.
"null"
2. Si votre projet contient plus d'une fonction main
, veuillez fusionner uniquement le fichier avec la fonction main
correcte. echo "null" > $IPCG_FILENAME
find ./src -name "*.ipcg" -exec cgmerge $IPCG_FILENAME $IPCG_FILENAME {} +
Le graphique final doit être placé dans le répertoire de l'analyseur callgraph. Étant donné que PGIS est actuellement utilisé pour l'analyse CG, l'intégralité du fichier programme généré est copié dans le répertoire PGIS. Actuellement, il est important que le fichier dans le répertoire PGIS soit nommé selon le modèle item_flavor.mcg
. Un élément représente une application cible. Plus d’informations sur les termes saveur et article dans la section suivante.
# Assuming $PIRA holds the top-level PIRA directory
$> cp my-app.mcg $PIRA/extern/install/pgis/bin/item_flavor.mcg
La configuration PIRA contient toutes les informations requises pour que PIRA puisse exécuter le processus automatique. Les différents répertoires qui doivent être spécifiés dans le fichier de configuration peuvent être soit des chemins absolus , soit des chemins relatifs au chemin d'exécution de pira . Les chemins peuvent contenir des variables d'environnement, par exemple $HOME
. Les exemples sont tirés de l'exemple GameOfLife dans ./test/integration/GameOfLife
.
L'utilisateur précise : le répertoire dans lequel rechercher les éléments définis ultérieurement, dans l'exemple, le répertoire est ./gol/serial_non_template
. Ces répertoires reçoivent des alias, qui sont déréférencés à l'aide du signe '%'. Un élément dans PIRA est une application cible, construite d'une manière spécifique, c'est la raison pour laquelle elle est regroupée dans la configuration sous builds .
{
"builds": {
"%gol": {
"items": {
"gol": {
...
}
}
}
}
"directories": {
"gol": "./gol/serial_non_template"
}
}
Chaque élément précise quel analyseur doit être utilisé. L'analyseur par défaut est livré avec PIRA et les sources peuvent être trouvées dans ./extern/src/metacg/pgis
ou l'installation dans ./extern/install/pgis/bin
, respectivement. L’analyseur est responsable du pilotage du raffinement de l’instrumentation et constitue donc un élément essentiel du cadre PIRA.
Le champ argmap spécifie les différents arguments transmis à l'application cible lors de l'exécution des expériences de performances. La manière dont les arguments sont transmis à l'application cible est définie par différents mappeurs . Dans l'exemple, un mappeur linéaire est utilisé, qui itère simplement les valeurs du paramètre nommé size dans l'ordre indiqué dans la liste.
"argmap": {
"mapper": "Linear",
"size": [50, 80, 110, 150, 300, 500]
}
Le champ Cubes est l'emplacement où PIRA doit stocker les profils Score-P obtenus. Il construira une arborescence de répertoires à cet emplacement, afin que l'utilisateur puisse, une fois PIRA terminé, invoquer facilement l'outil de modélisation Extra-P en lui passant simplement l'emplacement respectif, c'est-à-dire /tmp/pira dans l'exemple.
"cubes": "/tmp/pira"
Le champ des saveurs ajoute un autre niveau de distinction possible, car les applications cibles peuvent être créées dans différentes saveurs . Un exemple serait de spécifier différentes bibliothèques mathématiques avec lesquelles l'application cible doit se lier.
Enfin, le répertoire des foncteurs pointe PIRA vers l'emplacement où il recherche les fonctions Python fournies par l'utilisateur qui indiquent finalement à PIRA comment créer, exécuter et analyser l'application cible. Dans l'exemple, PIRA pointe vers un répertoire appelé foncteurs par rapport à l'emplacement de la configuration.
"flavors": [
"ct"
],
"functors": "./functors",
"mode": "CT"
Le champ mode , dans cette version de PIRA, est ignoré.
Désormais, l'utilisateur doit implémenter cinq foncteurs différents :
analyze_<ITEM>_<FLAVOR>.py
: appelle l'analyseur.clean_<ITEM>_<FLAVOR>.py
: nettoie le répertoire de construction.<ITEM>_<FLAVOR>.py
: build la version instrumentée.no_instr_<ITEM>_<FLAVOR>.py
: construit la version vanilla.runner_<ITEM>_<FLAVOR>.py
: exécute l'application cible. Les foncteurs prennent généralement en charge deux modes d'invocation : actif et passif . Le foncteur indique à PIRA quel mode il utilise en définissant la valeur respective sur True
dans le dictionnaire renvoyé par la fonction get_method()
.
En mode actif, le foncteur appelle lui-même les commandes requises, par exemple pour créer le logiciel. Lorsqu'il est invoqué, le foncteur reçoit un paramètre **kwargs
contenant, par exemple, le répertoire actuel et une instance d'un shell de sous-processus.
Le mode passif renvoie uniquement les commandes à exécuter, par exemple la chaîne make
pour invoquer un simple Makefile dans le répertoire de niveau supérieur de l'élément. Un paramètre kwargs
lui est également transmis qui contient des informations spécifiques, telles que des valeurs prédéfinies nécessaires à ajouter à CXXFLAGS ou des indicateurs d'éditeur de liens supplémentaires. Un exemple de foncteur passif peut être trouvé dans les répertoires examples
et test
. Actuellement, tous les foncteurs implémentés utilisent le mode passif.
PIRA transmet les arguments de mots-clés suivants à tous les foncteurs. De plus, différents composants PIRA peuvent transmettre des arguments supplémentaires.
Important : Nous livrons désormais notre propre version Score-P. Ainsi, il n'est plus nécessaire d'ajuster les commandes de compilation dans PIRA. Découvrez les foncteurs dans test/integration/AMG2013
pour des exemples d'utilisation des différentes informations.
Actuellement, aucune information n'est transmise à tous les foncteurs
[0]
accède au premier argument, [1]
au second, et ainsi de suite..so
implémentant les fonctions du wrapper MPI (crucial pour le filtrage MPI). Des paramètres supplémentaires sont requis pour certains modes d'analyse. Plus précisément, l'analyse de modélisation PIRA LIDe (voir ci-dessous) et Extra-P nécessitent des paramètres fournis par l'utilisateur. Créez un fichier JSON et fournissez son chemin vers PIRA à l'aide du commutateur --analysis-parameters
. L'exemple suivant contient des paramètres pour le mode de modélisation Extra-P. Les stratégies disponibles pour agréger plusieurs modèles Extra-P (lorsqu'une fonction est appelée dans différents contextes) sont : FirstModel
, Sum
, Average
, Maximum
.
{
"Modeling": {
"extrapolationThreshold": 2.1,
"statementThreshold": 200,
"modelAggregationStrategy": "Sum"
}
}
Pour plus de détails sur la fonction de détection de déséquilibre de charge, veuillez vous référer à [PI21]. Fournissez à l'invocation PIRA un chemin d'accès à un fichier de configuration à l'aide du paramètre --load-imbalance-detection
. Ce fichier JSON doit avoir la structure suivante :
{
"metricType": "ImbalancePercentage",
"imbalanceThreshold": 0.05,
"relevanceThreshold": 0.05,
"contextStrategy": "None",
"contextStepCount": 5,
"childRelevanceStrategy": "RelativeToMain",
"childConstantThreshold": 1,
"childFraction": 0.001
}
Pour exécuter PIRA sur un cluster avec le gestionnaire de charge de travail SLURM, appelez-le avec l'indicateur --slurm-config
. Donnez-lui le chemin d'accès à votre fichier de configuration du système batch. Voir les tests d'intégration suffixés par _Slurm
( test/integration/*_Slurm/
). PIRA prend actuellement en charge les systèmes batch avec le gestionnaire de charge de travail SLURM. PIRA prend en charge l'utilisation d'un système module
, que l'on peut trouver sur les clusters slurm.
Le fichier de configuration du système par lots est un fichier JSON structuré comme suit :
{
"general": {
"backend": "slurm",
"interface": "pyslurm",
"timings": "subprocess"
},
"module-loads": [
{
"name": "gcc",
"version": "8.5"
},
{
"name": "llvm",
"version": "10.0.0",
"depends-on": [
{
"name": "gcc",
"version": "8.5"
}
]
}
],
"batch-settings": {
"time_str": "00:10:00",
"mem_per_cpu": 3800,
"number_of_tasks": 1,
"partition": null,
"reservation": null,
"account": "your_account_here",
"cpus_per_task": 96
}
}
Panne:
general
: Vous permet de choisir de quelle manière PIRA exécutera votre code sur le système batch. Étant donné que chaque option de cette section est facultative, vous pouvez omettre toute la section si vous acceptez d'utiliser les valeurs par défaut :backend
: quel gestionnaire de charge de travail utiliser. Choix : slurm
, pour le gestionnaire de charge de travail slurm. Par défaut : slurm
, donc facultatif.interface
: De quelle manière PIRA doit interagir avec votre gestionnaire de système batch. Pour le backend SLURM, ce sont : pyslurm
, pour utiliser PySlurm (cela nécessite que PySlurm soit installé, voir cette section ; sbatch-wait
, pour utiliser sbatch
standard avec l'indicateur --wait
; os
, pour les appels d'interaction sbatch
et squeue
standard. Par défaut : pyslurm
, donc facultatif.timings
: Comment le timing du code cible doit être effectué. Choix : subprocess
, pour le timing avec un wrapper python et os.times
dans un sous-processus (exactement comme PIRA le fait s'il est exécuté localement) ; os
, pour utiliser /usr/bin/time
. Par défaut : subprocess
, donc facultatif.force-sequential
: false
par défaut. Définissez sur true
pour forcer PIRA/votre système batch à effectuer toutes les exécutions dans un ordre séquentiel (une seule exécution du code cible à la fois). Cela signifie que PIRA veillera à ce que votre système par lots exécute des répétitions, ainsi que différentes tâches de mise à l'échelle des expériences dans un ordre séquentiel. S'il est défini sur/à gauche sur false
PIRA essaiera de demander au système par lots d'effectuer autant d'exécutions que possible à chaque itération en parallèle.module-loads
: actuellement non utilisée dans PIRA, travail en cours ! Actuellement, vous devez charger tous les modules manuellement avant de démarrer PIRA ! Destiné à quels modules doivent être chargés avec le système module
. Cela nécessite qu'un module soit en place (les commandes module load
et module purge
peuvent être utilisées par PIRA). Si vous n'avez pas de système module
en place ou si vous ne souhaitez pas l'utiliser, omettez complètement cette section ou définissez "module-loads": null
. Pour spécifier les modules que PIRA doit charger, spécifiez une liste de modules, comme dans l'exemple ci-dessus.name
.version
est facultative, si elle n'est pas indiquée, elle dépendra de ce que le système module
charge comme version de module par défaut. Il est recommandé de toujours donner explicitement les versions.depends-on
est également facultatif. Donnez une liste des modules dont dépend ce module. Ces modules doivent avoir un name
et peuvent éventuellement avoir une version
donnée. Les dépendances définies ici sont utilisées par PIRA pour déterminer l'ordre dans lequel les modules doivent être chargésnull
, on suppose que ce module n'a aucune dépendance.depends-on
PIRA (essaiera de) charger les modules exactement dans l'ordre indiqué dans le fichier de configuration.batch-setting
: le matériel réel et les options de travail pour le système par lots. Certaines options de la section sont obligatoires, vous ne pouvez pas omettre cette section.time
: L'option sbatch --time
, obligatoire.mem-per-cpu
: L'option sbatch --mem-per-cpu
, obligatoire.ntasks
: L'option sbatch --ntasks
, obligatoire.partition
, reservation
, account
(tous par défaut sur null
= non donné), cpus-per-task
(par défaut sur 4
), exclusive
(par défaut sur true
; non pris en charge avec pyslurm
) et cpu-freq
(par défaut, null
).sbatch
vous ne pouvez pas définir dans cette configuration. Cela est dû à certaines options utilisées en interne par PIRA, par exemple l'option --array
, pour mapper les répétitions sur des tableaux de tâches. Comment et quelle version de PySlurm installer sur votre cluster dépend fortement de votre version SLURM et de votre installation SLURM. La solution d'installation et de packaging pour pyslurm avec PIRA est en cours de réalisation. Reportez-vous à leur README. Vous pouvez essayer certaines des solutions suivantes :
include
et un répertoire lib
.python3 setup.py build --slurm-lib=/opt/slurm/21.08.6/lib --slurm-inc=/opt/slurm/21.08.6/include
python3 setup.py install --slurm-lib=/opt/slurm/21.08.6/lib --slurm-inc=/opt/slurm/21.08.6/include
.