OpenHMPP (HMPP [1] para programación en paralelo híbrida multinúcleo): estándar de programación para computación heterogénea . Basado en un conjunto de directivas del compilador, estándar es un modelo de programación diseñado para manejar aceleradores de hardware sin la complejidad asociada con la programación de GPU . Este enfoque basado en directivas se ha implementado porque permiten una relación flexible entre un código de aplicación y el uso de un acelerador de hardware (HWA).
Introducción
El modelo de programación basado en directivas OpenHMPP ofrece una sintaxis para descargar cálculos en aceleradores de hardware y optimizar el movimiento de datos hacia / desde la memoria del hardware.
El modelo se basa en trabajos inicializados por CAPS (Compiler and Architecture for Embedded and Superscalar Processors) , un proyecto común de INRIA , CNRS , la Universidad de Rennes 1 y el INSA de Rennes.
Concepto OpenHMPP
OpenHMPP se basa en el concepto de codelets, funciones que se pueden ejecutar de forma remota en HWA.
El concepto de codelet de OpenHMPP
Un codelet tiene las siguientes propiedades:
- Es una función pura .
- No contiene declaraciones de variables estáticas o volátiles ni se refiere a ninguna variable global, excepto si estas han sido declaradas por una directiva HMPP como "residente".
- No contiene ninguna llamada a función con un cuerpo invisible (que no se puede insertar). Esto incluye el uso de bibliotecas y funciones del sistema como malloc, printf, ...
- Cada llamada a función debe hacer referencia a una función pura estática (sin punteros de función).
- No devuelve ningún valor (función nula en C o una subrutina en Fortran ).
- El número de argumentos debe ser fijo (es decir, no puede ser una función variada como en stdarg.h en C).
- No es recursivo.
- Se supone que sus parámetros no tienen alias (consulte Alias (computación) y Alias de puntero ).
- No contiene directivas de sitios de llamadas (es decir, RPC a otro codelet) u otras directivas HMPP.
Estas propiedades garantizan que un RPC de codelet pueda ser ejecutado de forma remota por un HWA. Este RPC y sus transferencias de datos asociadas pueden ser asincrónicas.
RPC de Codelet
HMPP proporciona RPC sincrónico y asincrónico. La implementación del funcionamiento asíncrono depende del hardware.
Modelo de memoria HMPP
HMPP considera dos espacios de direcciones: el procesador host y la memoria HWA.
Concepto de directivas
Las directivas OpenHMPP pueden verse como “metainformación” agregada en el código fuente de la aplicación. Son metainformaciones seguras, es decir, no cambian el comportamiento del código original. Abordan la ejecución remota (RPC) de una función, así como las transferencias de datos hacia / desde la memoria HWA.
La siguiente tabla presenta las directivas OpenHMPP. Las directivas OpenHMPP abordan diferentes necesidades: algunas de ellas están dedicadas a declaraciones y otras están dedicadas a la gestión de la ejecución.
Instrucciones de flujo de control | Directivas para la gestión de datos | |
---|---|---|
Declaraciones | grupo de codelet | mapa residente mapbyname |
Directivas operativas | región de sincronización del sitio de llamadas | Asignar versión avanzada cargar almacén delegado |
Concepto de conjunto de directivas
Uno de los puntos fundamentales del enfoque HMPP es el concepto de directivas y sus etiquetas asociadas que permite exponer una estructura coherente sobre todo un conjunto de directivas difundidas en una aplicación.
Hay dos tipos de etiquetas:
- Uno asociado a un codelet. En general, las directivas que llevan este tipo de etiquetas se limitan a la gestión de un solo codelet (denominado codelet autónomo en el resto del documento para distinguirlo del grupo de codelets).
- Uno asociado a un grupo de codelets. Estas etiquetas se indican de la siguiente manera: "
", donde "LabelOfGroup" es un nombre especificado por el usuario. En general, las directivas que tienen una etiqueta de este tipo se refieren a todo el grupo. El concepto de grupo está reservado a una clase de problemas que requieren una gestión específica de los datos en toda la aplicación para obtener rendimiento.
Sintaxis de las directivas OpenHMPP
Para simplificar las notaciones, se utilizarán expresiones regulares para describir la sintaxis de las directivas HMPP.
La siguiente convención de colores se utiliza para la descripción de las directivas de sintaxis:
- Las palabras clave reservadas de HMPP están en verde ;
- Los elementos gramaticales que se pueden rechazar en las palabras clave de HMPP están en rojo ;
- Las variables del usuario permanecen en negro.
Sintaxis general
La sintaxis general de las directivas OpenHMPP es:
- Para lenguaje C:
#pragma hmpp < grp_label > [codelet_label]? directive_type [ , directive_parameters ] * [ & ]
- Para el idioma FORTRAN:
! $ hmpp < grp_label > [codelet_label]? directive_type [ , directive_parameters ] * [ & ]
Dónde:
: es un identificador único que nombra un grupo de codelets. En los casos en los que no se definen grupos en la aplicación, esta etiqueta simplemente puede faltar. El nombre de la etiqueta legal debe seguir esta gramática: [az, AZ, _] [az, AZ, 0-9, _] *. Tenga en cuenta que los caracteres “<>” pertenecen a la sintaxis y son obligatorios para este tipo de etiqueta.codelet_label
: es un identificador único que nombra un codelet. El nombre de la etiqueta legal debe seguir esta gramática: [az, AZ, _] [az, AZ, 0-9, _] *directive
: es el nombre de la directiva;directive_parameters
: designa algunos parámetros asociados a la directiva. Estos parámetros pueden ser de diferentes tipos y especificar algunos argumentos dados a la directiva o un modo de ejecución (asíncrono o síncrono, por ejemplo);[&]
: es un carácter que se usa para continuar la directiva en la siguiente línea (lo mismo para C y FORTRAN).
Parámetros de directiva
Los parámetros asociados a una directiva pueden ser de diferentes tipos. A continuación se muestran los parámetros de la directiva definidos en OpenHMPP:
version = major.minor[.micro]
: especifica la versión de las directivas HMPP que debe considerar el preprocesador.args[arg_items].size={dimsize[,dimsize]*}
: especifica el tamaño de un parámetro no escalar (una matriz).args[arg_items].io=[in|out|inout]
: indica que los argumentos de la función especificada son de entrada, salida o ambos. De forma predeterminada, los argumentos no calificados son entradas.cond = "expr"
: especifica una condición de ejecución como una expresión booleana C o Fortran que debe ser verdadera para iniciar la ejecución del grupo o codelets.target=target_name[:target_name]*
: especifica qué objetivos intentar utilizar en el orden dado.asynchronous
: especifica que la ejecución del codelet no se bloquea (el valor predeterminado es sincrónico).args[
: indica que los parámetros especificados están precargados. Solo se pueden precargar parámetros in o inout.].advancedload=true args[arg_items].noupdate=true
: esta propiedad especifica que los datos ya están disponibles en el HWA y que no es necesario transferirlos. Cuando se establece esta propiedad, no se realiza ninguna transferencia en el argumento consideradoargs[
:].addr=" "
es una expresión que da la dirección de los datos a cargar.args[
: indica que el argumento se cargará solo una vez.].const=true
Directivas OpenHMPP
Directivas para declarar y ejecutar un codelet
Una codelet
directiva declara que un cálculo se ejecutará de forma remota en un acelerador de hardware. Para la codelet
directiva:
- La etiqueta de codelet es obligatoria y debe ser única en la aplicación.
- La etiqueta de grupo no es necesaria si no se define ningún grupo.
- La directiva codelet se inserta justo antes de la declaración de función.
La sintaxis de la directiva es:
#pragma hmpp < grp_label > codelet_label codelet [ , version = major.minor [.micro]?]? [ , args [ arg_items ] .io = [[ en | fuera | inout ]] * [ , args [ arg_items ] .size = { dimsize [, dimsize] * } ] * [ , args [ arg_items ] .const = true ] * [ , cond = "expr"] [ , target = target_name [: target_name ] *]
Se puede agregar más de una directiva de codelet a una función para especificar diferentes usos o diferentes contextos de ejecución. Sin embargo, solo puede haber una directiva de codelet para una etiqueta de sitio de llamada determinada.
La callsite
directiva especifica cómo se usa un codelet en un punto dado del programa.
La sintaxis de la directiva es:
#pragma hmpp < grp_label > codelet_label callsite [ , asincrónico ]? [ , args [ arg_items ] .size = { dimsize [, dimsize] * } ] * [ , args [ arg_items ] .advancedload = [[ true | falso ]] * [ , args [ arg_items ] .addr = " expr " ] * [ , args [ arg_items ] .noupdate = true ] *
Aquí se muestra un ejemplo:
/ * declaración del codelet * / #pragma hmpp simple1 codelet, args [outv] .io = inout, target = CUDA static void matvec ( int sn , int sm , float inv [ sm ], float inm [ sn ] [ sm ] , flotar * outv ) { int i , j ; para ( i = 0 ; i < sm ; i ++ ) { float temp = outv [ i ]; para ( j = 0 ; j < sn ; j ++ ) { temp + = inv [ j ] * inm [ i ] [ j ]; } outv [ i ] = temp ; } int main ( int argc , char ** argv ) { int n ; ........ / * Uso codelet * / #pragma hmpp simple1 callsite, args [OUTV] .size = {n} matvec ( n , m , myinc , inm , myoutv ); ........ }
En algunos casos se requiere una gestión específica de los datos a lo largo de la aplicación (optimización de movimientos de datos de CPU / GPU, variables compartidas ...).
La group
directiva permite la declaración de un grupo de codelets. Los parámetros definidos en esta directiva se aplican a todos los codelets que pertenecen al grupo. La sintaxis de la directiva es:
#pragma hmpp < grp_label > grupo [ , versión =. [ , target = target_name [: target_name ] *]]? [ , cond = " expr " ]?[. ]?]?
Directivas de transferencia de datos para optimizar la sobrecarga de comunicación
Cuando se utiliza un HWA, el principal cuello de botella suele ser la transferencia de datos entre el HWA y el procesador principal.
Para limitar la sobrecarga de comunicación, las transferencias de datos se pueden superponer con ejecuciones sucesivas del mismo codelet utilizando la propiedad asincrónica de HWA.
- asignar directiva
La allocate
directiva bloquea el HWA y asigna la cantidad de memoria necesaria.
#pragma hmpp < grp_label > allocate [ , args [ arg_items ] .size = { dimsize [, dimsize] * } ] *
- directiva de liberación
La release
directiva especifica cuándo liberar el HWA para un grupo o un codelet independiente.
Lanzamiento de #pragma hmpp < grp_label >
- directiva de carga avanzada
La advancedload
directiva busca datos antes de la ejecución remota del codelet.
#pragma hmpp < grp_label > [codelet_label]? carga avanzada , argumentos [ elementos_arg ] [ , argumentos [ elementos_arg ] .size = { dimsize [, dimsize] * } ] * [ , args [ arg_items ] .addr = " expr " ] * [ , args [ arg_items ] .section = { [ subscript_triplet , ] + } ] * [ , asincrónico ]
- directiva de almacén delegado
La delegatedstore
directiva es una barrera de sincronización para esperar a que se complete la ejecución de un codelet asincrónico y luego descargar los resultados.
#pragma hmpp < grp_label > [codelet_label]? almacén delegado , argumentos [ elementos_arg ] [ , elementos [ elementos_arg ] .addr = " expr " ] * [ , args [ arg_items ] .section = { [ subscript_triplet , ] + } ] *
- Cálculos asincrónicos
La synchronize
directiva especifica esperar hasta que se complete una ejecución asincrónica del sitio de llamadas. Para la directiva de sincronización, la etiqueta de codelet siempre es obligatoria y la etiqueta de grupo es necesaria si el codelet pertenece a un grupo.
#pragma hmpp < grp_label > codelet_label sincronizar
- Ejemplo
En el siguiente ejemplo, la inicialización del dispositivo, la asignación de memoria y la carga de los datos de entrada se realizan solo una vez fuera del ciclo y no en cada iteración del ciclo.
La synchronize
directiva permite esperar a que se complete la ejecución asincrónica del codelet antes de lanzar otra iteración. Finalmente, la delegatedstore
directiva fuera del bucle carga el resultado de sgemm.
int main ( int argc , char ** argv ) { #pragma hmpp sgemm allocate, args [vin1; vin2; vout] .size = {size, size} #pragma hmpp sgemm advancedload, args [vin1; vin2; vout], args [m, n, k, alpha, beta] for ( j = 0 ; j < 2 ; j ++ ) { #pragma hmpp sgemm callsite, asynchronous, args [vin1; vin2; vout] .advancedload = true, args [m, n, k, alpha, beta] .advancedload = verdadero sgemm ( tamaño , tamaño , tamaño , alfa , vin1 , vin2 , beta , vout ); #pragma hmpp sgemm sincronizar } #pragma hmpp sgemm delegatedstore, args [vout] #pragma hmpp sgemm release
Compartir datos entre codelets
Esas directivas mapean juntos todos los argumentos que comparten el nombre de pila para todo el grupo.
Los tipos y dimensiones de todos los argumentos asignados deben ser idénticos.
La map
directiva mapea varios argumentos en el dispositivo.
#pragma hmpp < grp_label > map, args [ arg_items ]
Esta directiva es bastante similar a la map
directiva excepto que los argumentos que se mapearán se especifican directamente por su nombre. La mapbyname
directiva es equivalente a varias map
directivas.
#pragma hmpp < grp_label > mapbyname [ , variableName] +
Variable global
La resident
directiva declara algunas variables como globales dentro de un grupo. A continuación, se puede acceder directamente a esas variables desde cualquier codelet que pertenezca al grupo. Esta directiva se aplica a la declaración de declaración que la sigue en el código fuente.
La sintaxis de esta directiva es:
#pragma hmpp < grp_label > residente [ , args [:: var_name ] .io = [[ in | fuera | inout ]] * [ , args [:: var_name ] .size = { dimsize [, dimsize] * } ] * [ , args [:: var_name ] .addr = " expr " ] * [ , args [:: var_name ] .const = true ] *
La notación ::var_name
con el prefijo ::
indica la variable de una aplicación declarada como residente.
Aceleración de regiones
Una región es una combinación de las directivas codelet / callsite. El objetivo es evitar la reestructuración del código para construir el codelet. Por lo tanto, todos los atributos disponibles para codelet
o callsite
directivas se pueden usar en regions
directivas.
En lenguaje C:
#pragma hmpp [< MiGrupo >] [ etiqueta ] región [ , args [ arg_items ] .io = [[ in | fuera | inout ]] * [ , cond = " expr "] < [ , args [ arg_items ] .const = true ] * [ , target = target_name [ : target_name ] *] [ , args [ arg_items ] .size = { dimsize [ , dimsize] * } ] * [ , args [ arg_items ] .advancedload = [[ true | falso ]] * [ , args [ arg_items ] .addr = " expr " ] * [ , args [ arg_items ] .noupdate = true ] * [ , asincrónico ]? [ , privado = [ arg_items ] ] * {DECLARACIONES DE BLOQUE C }
Implementaciones
OpenHMPP Open Standard se basa en la versión 2.3 de HMPP (mayo de 2009, CAPS entreprise).
El modelo de programación basado en directivas de OpenHMPP se implementa en:
- Compiladores CAPS, compiladores CAPS Entreprise para computación híbrida
- PathScale ENZO Compiler Suite (compatible con las GPU NVIDIA)
OpenHMPP es utilizado por actores de HPC [ ¿quién? ] en Petróleo y Gas, [ cita requerida ] Energía, [ cita requerida ] Fabricación, [ cita requerida ] Finanzas, [ cita requerida ] Educación e Investigación. [ cita requerida ]
Ver también
Referencias
- ^ Dolbeau, Romain; Bihan, Stéphane; Bodin, François (4 de octubre de 2007). HMPP: un entorno de programación en paralelo híbrido de varios núcleos (PDF) . Taller de Procesamiento de Propósito General en Unidades de Procesamiento de Gráficos . Archivado desde el original (PDF) el 16 de enero de 2014 . Consultado el 14 de enero de 2014 .
enlaces externos
- CAPS Entreprise SAS y PathScale, Inc colaborarán conjuntamente para hacer de HMPP un nuevo estándar abierto
- Cómo el hardware dará forma a los lenguajes por David Chisnall
- Aceleración de código con HMPP por ICHEC (Centro irlandés de informática de alta gama )
- Expérience de programmation avec HMPP By IRMA (Institut de Recherche Mathématique Avancée) - FORTRAN examples
- Puerto HMPP por CEA (Commissariat à l'Energie Atomique et aux Energies Alternatives) para PRACE (Asociación para la Computación Avanzada en Europa)