El marco de automatización de refinamiento de instrumentos de rendimiento PIRA aborda la tarea que requiere mucho tiempo de generar una medición de rendimiento razonable para una base de código desconocida cuando se utiliza Score-P. Para obtener más información, consulte nuestros artículos:
[PI18] | Jan-Patrick Lehr, Alexander Hück, Christian Bischof. PIRA: automatización del refinamiento de la instrumentación de rendimiento. En 5to Taller Internacional ACM SIGPLAN sobre Inteligencia Artificial y Métodos Empíricos para Ingeniería de Software y Sistemas de Computación Paralela (AI-SEPS) , páginas 1-10, ACM, 2018. |
[PI19] | Jan-Patrick Lehr, Alexandru Calotoiu, Christian Bischof, Felix Wolf. Refinamiento automático de instrumentación para modelado de desempeño empírico. En Taller internacional sobre herramientas de programación y visualización de rendimiento (ProTools) , páginas 40-47, IEEE, 2019. |
[PI21] | Peter Arzt, Yannic Fischler, Jan-Patrick Lehr, Christian Bischof. Detección automática de desequilibrio de carga generalizada en aplicaciones MPI. En Euro-Par 2021: Procesamiento Paralelo. Apuntes de conferencias sobre informática, vol 12820 , páginas 19-34, Springer, 2021. |
PIRA ejecuta las siguientes cuatro fases (se repiten 2-4):
PIRA admite el filtrado de funciones en tiempo de compilación y en tiempo de ejecución , incluido el filtrado en tiempo de ejecución de funciones MPI a través de contenedores generados automáticamente. En el filtrado en tiempo de compilación, solo se instrumentan las funciones deseadas en tiempo de compilación, lo que reduce significativamente la influencia general de la medición. Por el contrario, en el filtrado en tiempo de ejecución, el compilador inserta enlaces de instrumentación en cada función de la aplicación de destino y el filtrado se realiza en tiempo de ejecución.
PIRA requiere CMake (>=3.16), Clang/LLVM 10, Python 3, Qt5 y OpenMPI 4. Este (o MetaCG) descargará (y compilará) más
Si desea crear PIRA en un entorno sin acceso a Internet, consulte el script resources/build_submodules.sh
y ajústelo a sus necesidades.
Clona el repositorio de PIRA.
$> git clone https://github.com/tudasc/pira
$> cd pira
En segundo lugar, cree los submódulos dependientes utilizando el script proporcionado o pase valores para las diferentes opciones (consulte la información de uso a través de -h
para conocer las opciones disponibles). Todos los archivos descargados y creados se colocarán en external/src/
mientras que todas las instalaciones se colocarán en external/install/
. Especifique la cantidad de procesos de compilación que se generarán para la compilación de los elementos externos de PIRA. El script descargará las dependencias de PIRA en su versión predeterminada. Estas versiones también se prueban en nuestro CI y se espera que funcionen.
$> cd resources
$> ./build_submodules.sh -p <ncores>
Como paso final, el script de compilación escribirá las rutas de instalación de los submódulos en el archivo resources/setup_paths.sh
. Si desea reconstruir PIRA, recuerde git restore
.
También proporcionamos un Dockerfile
(experimental) para construir PIRA y probarlo.
$> podman build -t pira:master -f docker/Dockerfile .
Cuando se ejecuta dentro del contenedor, por ejemplo, las pruebas de integración, invoque los scripts de la siguiente manera.
$> 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
Para ver un ejemplo completo de cómo usar PIRA, consulte los scripts run.sh
en la carpeta /test/integration/*
. Un punto de partida potencialmente bueno es la carpeta GameOfLife
y su caso de prueba.
Primero, configure las rutas requeridas obteniendo el script en la carpeta resources
.
$> cd resources/
$> . setup_paths.sh
Luego, puede ejecutar una aplicación de ejemplo de PIRA en una implementación muy simple del Juego de la vida de Conway utilizando el script run.sh
proporcionado en la carpeta ./test/integration/GameOfLife
.
$> cd ./test/integration/GameOfLife
$> ./run.sh
El script realiza todos los pasos necesarios desde el principio, es decir, prepara todos los componentes para un nuevo código de destino, para finalmente invocar PIRA. En las secciones siguientes, los pasos se explican con más detalle. Los pasos son:
config
Ruta al archivo de configuración (argumento requerido)--config-version [1,2]
Versión de la configuración de PIRA, 2 es la predeterminada y se recomienda; 1 está en desuso.--runtime-filter
Utilice el filtrado en tiempo de ejecución, el valor predeterminado es falso. En el filtrado en tiempo de compilación, las funciones no se instrumentan en tiempo de compilación, lo que reduce significativamente la influencia general de la medición, pero requiere que el objetivo se reconstruya en cada iteración. Por el contrario, con el filtrado en tiempo de ejecución, el compilador inserta enlaces de instrumentación en cada función de la aplicación de destino.--iterations [number]
Número de iteraciones de Pira, el valor predeterminado es 3.--repetitions [number]
Número de repeticiones de medición, el valor predeterminado es 3.--tape
Ubicación donde se debe escribir una cinta de registro (algo extensa).--extrap-dir
El directorio base donde se ubica la estructura de carpetas Extra-p.--extrap-prefix
Prefijo extra-P, debe ser una secuencia de caracteres.--version
Imprime el número de versión de la instalación de PIRA.--analysis-parameters
Ruta al archivo de configuración que contiene parámetros de análisis para PGIS. Requerido tanto para el modo Extra-P como para el LIDe.--slurm-config [path to slurm cfg file]
Permite ejecutar el código de destino en un clúster de slurm. Se necesita un archivo de configuración de slurm. Consulte esta sección para obtener más información. --hybrid-filter-iters [number]
Vuelva a compilar después de [número] iteraciones, use filtrado de tiempo de ejecución en el medio.--export
Adjunta los modelos Extra-P generados y los tamaños de conjuntos de datos al archivo IPCG del objetivo.--export-runtime-only
Requiere --export
; Adjunta solo el valor medio del tiempo de ejecución de todas las repeticiones a las funciones. Solo disponible cuando no se usa Extra-P.--load-imbalance-detection [path to cfg file]
Habilita y configura el modo de detección de desequilibrio de carga. Por favor lea esta sección para más información. PIRA utiliza información del código fuente para construir una instrumentación inicial y decidir qué funciones agregar a una instrumentación durante el refinamiento iterativo. Proporciona una herramienta de gráfico de llamadas basada en Clang que recopila toda la información requerida y genera la información en un archivo .json
. Puede encontrar la herramienta cgcollector
en el subdirectorio ./extern/src/metacg/cgcollector
. PIRA requiere que el archivo callgraph esté en el formato de archivo MetaCG en la versión 2 (MetaCG v2).
Puede encontrar más información sobre CCGollector y sus componentes en la documentación de MetaCG.
La aplicación de CCGollector suele realizarse en dos pasos.
Al principio, se invoca cgc
en cada archivo fuente del proyecto. p.ej:
for f in $(find ./src -type f ( -iname "*.c" -o -iname "*.cpp" ) ); do
cgc --metacg-format-version=2 $f
done
Los archivos .ipcg
creados en el paso 1 luego se fusionan en un archivo general usando cgmerge
.
"null"
2. Si su proyecto contiene más de una función main
, combine solo el archivo con la función main
correcta. echo "null" > $IPCG_FILENAME
find ./src -name "*.ipcg" -exec cgmerge $IPCG_FILENAME $IPCG_FILENAME {} +
El gráfico final debe colocarse en el directorio del analizador de gráficos de llamada. Dado que PGIS se utiliza actualmente para el análisis CG, el archivo de programa completo generado se copia en el directorio PGIS. Actualmente, es importante que el archivo en el directorio PGIS tenga el nombre siguiendo el patrón item_flavor.mcg
. Un elemento representa una aplicación de destino. Más información sobre los términos sabor y artículo en la siguiente sección.
# Assuming $PIRA holds the top-level PIRA directory
$> cp my-app.mcg $PIRA/extern/install/pgis/bin/item_flavor.mcg
La configuración de PIRA contiene toda la información necesaria para que PIRA ejecute el proceso automático. Los diversos directorios que deben especificarse en el archivo de configuración pueden ser rutas absolutas o rutas relativas a la ruta de ejecución de pira . Las rutas pueden contener variables de entorno, por ejemplo, $HOME
. Los ejemplos están tomados del ejemplo GameOfLife en ./test/integration/GameOfLife
.
El usuario especifica: el directorio en el que buscar elementos definidos posteriormente, en el ejemplo, el directorio es ./gol/serial_non_template
. Estos directorios reciben alias, a los que se les desreferencia utilizando el signo '%'. Un elemento en PIRA es una aplicación de destino, construida de una manera específica, razón por la cual se agrupa en la configuración en compilaciones .
{
"builds": {
"%gol": {
"items": {
"gol": {
...
}
}
}
}
"directories": {
"gol": "./gol/serial_non_template"
}
}
Cada elemento especifica qué analizador se debe utilizar. El analizador predeterminado se envía con PIRA y las fuentes se pueden encontrar en ./extern/src/metacg/pgis
o la instalación en ./extern/install/pgis/bin
, respectivamente. El analizador es responsable de dirigir el refinamiento de la instrumentación y, por lo tanto, es una parte esencial del marco PIRA.
El campo argmap especifica los diferentes argumentos que se pasan a la aplicación de destino cuando se ejecutan los experimentos de rendimiento. Diferentes mapeadores definen cómo se pasan los argumentos a la aplicación de destino. En el ejemplo, se utiliza un asignador lineal , que simplemente itera los valores del parámetro denominado tamaño en el orden indicado en la lista.
"argmap": {
"mapper": "Linear",
"size": [50, 80, 110, 150, 300, 500]
}
El campo de cubos es la ubicación donde PIRA debe almacenar los perfiles Score-P obtenidos. Construirá un árbol de directorios en esa ubicación, de modo que el usuario pueda, una vez finalizado PIRA, también invocar fácilmente la herramienta de modelado Extra-P simplemente pasándole la ubicación respectiva, es decir, /tmp/pira en el ejemplo.
"cubes": "/tmp/pira"
El campo de sabores agrega otro nivel de posible distinción, ya que las aplicaciones de destino se pueden crear en diferentes sabores . Un ejemplo sería especificar diferentes bibliotecas matemáticas con las que debe vincularse la aplicación de destino.
Finalmente, el directorio de functors señala a PIRA la ubicación donde busca las funciones de Python proporcionadas por el usuario que, en última instancia, le dicen a PIRA cómo construir, ejecutar y analizar la aplicación de destino. En el ejemplo, PIRA apunta a un directorio llamado funtores en relación con la ubicación de la configuración.
"flavors": [
"ct"
],
"functors": "./functors",
"mode": "CT"
El campo modo , en esta versión de PIRA, se ignora.
A partir de ahora, el usuario necesita implementar cinco functores diferentes:
analyze_<ITEM>_<FLAVOR>.py
: invoca el analizador.clean_<ITEM>_<FLAVOR>.py
: limpia el directorio de compilación.<ITEM>_<FLAVOR>.py
: construye la versión instrumentada.no_instr_<ITEM>_<FLAVOR>.py
: construye la versión básica.runner_<ITEM>_<FLAVOR>.py
: ejecuta la aplicación de destino. Los functores, generalmente, admiten dos modos de invocación: activo y pasivo . El functor le dice a PIRA qué modo utiliza estableciendo el valor respectivo en True
en el diccionario devuelto por la función get_method()
.
En modo activo, el propio functor invoca los comandos necesarios, por ejemplo, para construir el software. Cuando se invoca, al functor se le pasa un parámetro **kwargs
que contiene, por ejemplo, el directorio actual y una instancia de un shell de subproceso.
El modo pasivo únicamente devuelve los comandos a ejecutar, por ejemplo, la cadena make
para invocar un Makefile simple en el directorio de nivel superior del elemento. También se le pasa un parámetro kwargs
que contiene información específica, como valores predefinidos necesarios para agregar a CXXFLAGS o indicadores de vinculador adicionales. Se puede encontrar un ejemplo de functor pasivo en los directorios examples
y test
. Actualmente, todos los funtores implementados utilizan el modo pasivo.
PIRA pasa los siguientes argumentos de palabras clave a todos los functores. Además, diferentes componentes de PIRA pueden pasar argumentos adicionales.
Importante : ahora enviamos nuestra propia versión de Score-P. Por lo tanto, ya no es necesario ajustar los comandos de compilación en PIRA. Consulte los functores en test/integration/AMG2013
para ver ejemplos de usos de la diferente información.
Actualmente, no se pasa información a todos los functores.
[0]
accede al primer argumento, [1]
al segundo, y así sucesivamente..so
que implementa las funciones de contenedor MPI (crucial para el filtrado MPI). Se requieren parámetros adicionales para algunos modos de análisis. Específicamente, el análisis de modelado PIRA LIDe (ver más abajo) y Extra-P requiere parámetros proporcionados por el usuario. Cree un archivo JSON y proporcione su ruta a PIRA usando el interruptor --analysis-parameters
. El siguiente ejemplo contiene parámetros para el modo de modelado Extra-P. Las estrategias disponibles para agregar múltiples modelos Extra-P (cuando se llama a una función en diferentes contextos) son: FirstModel
, Sum
, Average
, Maximum
.
{
"Modeling": {
"extrapolationThreshold": 2.1,
"statementThreshold": 200,
"modelAggregationStrategy": "Sum"
}
}
Para obtener más detalles sobre la función de detección de desequilibrio de carga, consulte [PI21]. Proporcione a la invocación de PIRA una ruta a un archivo de configuración utilizando el parámetro --load-imbalance-detection
. Se requiere que este archivo JSON tenga la siguiente estructura:
{
"metricType": "ImbalancePercentage",
"imbalanceThreshold": 0.05,
"relevanceThreshold": 0.05,
"contextStrategy": "None",
"contextStepCount": 5,
"childRelevanceStrategy": "RelativeToMain",
"childConstantThreshold": 1,
"childFraction": 0.001
}
Para ejecutar PIRA en un clúster con el administrador de carga de trabajo SLURM, invoquelo con el indicador --slurm-config
. Indique la ruta al archivo de configuración de su sistema por lotes. Consulte las pruebas de integración con el sufijo _Slurm
( test/integration/*_Slurm/
). Actualmente, PIRA admite sistemas por lotes con el administrador de carga de trabajo SLURM. PIRA admite el uso de un sistema module
, que se puede encontrar en grupos de barrios marginales.
El archivo de configuración del sistema por lotes es un archivo JSON, que está estructurado de la siguiente manera:
{
"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
}
}
Descomponer:
general
: Le permite elegir de qué manera PIRA ejecutará su código en el sistema por lotes. Dado que cada opción en esta sección es opcional, puede omitir toda la sección, si está de acuerdo con el uso de los valores predeterminados:backend
: qué administrador de carga de trabajo usar. Opciones: slurm
, para el administrador de cargas de trabajo de slurm. Predeterminado: slurm
, por lo tanto opcional.interface
: De qué manera PIRA debe interactuar con el administrador de su sistema por lotes. Para el backend de SLURM, estos son: pyslurm
, para usar PySlurm (esto requiere que PySlurm esté instalado, consulte esta sección; sbatch-wait
, para usar sbatch
estándar con el indicador --wait
; os
, para llamadas de interacción estándar sbatch
y squeue
. Valor predeterminado: pyslurm
, por lo tanto opcional.timings
: cómo se debe realizar la sincronización del código de destino. Opciones: subprocess
, para cronometrar con un contenedor de Python y os.times
en un subproceso (exactamente como lo hace PIRA si se ejecuta localmente); os
, para usar /usr/bin/time
. Predeterminado: subprocess
, por lo tanto opcional.force-sequential
: predeterminado false
. Configúrelo en true
para forzar a PIRA/su sistema por lotes a realizar todas las ejecuciones en orden secuencial (solo una ejecución del código de destino a la vez). Esto significa que PIRA se encargará de que su sistema por lotes ejecute repeticiones, así como diferentes trabajos en experimentos de escalado en orden secuencial. Si se establece en/se deja en false
PIRA intentará indicarle al sistema por lotes que realice tantas ejecuciones como sea posible dentro de cada iteración en paralelo.module-loads
: Actualmente no está en uso en PIRA, ¡trabajo en progreso! Actualmente, es necesario cargar todos los módulos manualmente antes de iniciar PIRA. Significa qué módulos deben cargarse con el sistema module
. Esto requiere que haya uno en su lugar (PIRA puede usar los comandos module load
y module purge
). Si no tiene un sistema module
implementado o no desea usarlo, omita esta sección por completo o configure "module-loads": null
. Para especificar los módulos que PIRA debe cargar, especifique una lista de módulos, como en el ejemplo anterior.name
.version
es opcional, si no se proporciona, dependerá de lo que el sistema module
cargue como versión predeterminada del módulo. Se recomienda dar siempre versiones explícitamente.depends-on
también es opcional. Proporcione una lista de módulos de los que depende este módulo. Estos módulos deben tener un name
y, opcionalmente, pueden tener una version
. PIRA utiliza las dependencias definidas aquí para determinar el orden en el que se deben cargar los módulos.null
, se supone que este módulo no tiene dependencias.depends-on
PIRA (intentará) cargar los módulos exactamente en el orden que se proporcionó en el archivo de configuración.batch-setting
: El hardware real y las opciones de trabajo para el sistema por lotes. Algunas opciones de la sección son obligatorias, no puedes omitir esta sección.time
: La opción sbatch --time
, obligatoria.mem-per-cpu
: La opción sbatch --mem-per-cpu
, obligatoria.ntasks
: la opción sbatch --ntasks
, obligatoria.partition
, reservation
, account
(todo predeterminado es null
= no proporcionado), cpus-per-task
(predeterminado en 4
), exclusive
(predeterminado en true
; no compatible con pyslurm
) y cpu-freq
(el valor predeterminado es null
).sbatch
que no puede definir en esta configuración. Esto se debe a algunas opciones utilizadas internamente por PIRA, por ejemplo la opción --array
, para asignar las repeticiones a matrices de trabajos. Cómo y qué versión de PySlurm instalar en su clúster depende en gran medida de su versión de SLURM y de su instalación de SLURM. La solución de instalación y empaquetado de pyslurm con PIRA está en proceso. Consulte su LÉAME. Podrías probar algunos de los siguientes:
include
y 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
.