¿Cuántos núcleos de procesador Intel tiene en su computadora? Si utiliza un sistema basado en Intel, en la gran mayoría de los casos, deberá agregar uno a su respuesta. La composición de casi todos los procesadores Intel: desde Atom hasta Xeon E3, por supuesto, sin perderse el Core, durante muchos años ahora incluye el núcleo de gráficos integrados Intel Graphics, que es esencialmente un procesador completo y, en consecuencia, capaz de mostrar imágenes en la pantalla y acelerar el video, pero también realiza cálculos de propósito general "ordinarios". ¿Cómo se puede usar esto de manera efectiva? Mira debajo del corte.

Primero, explicaremos brevemente por qué vale la pena confiar en una GPU Intel. Por supuesto, el rendimiento de la CPU en el sistema casi siempre excede significativamente la GPU, por eso también es el procesador central.
Pero es interesante observar que el rendimiento de las GPU integradas de Intel en la última década ha crecido en términos porcentuales mucho más que el de la CPU, y esta tendencia ciertamente continuará con la llegada de nuevas tarjetas gráficas discretas de Intel. Además, la GPU, en virtud de su arquitectura (muchos dispositivos de ejecución de vectores), es mucho más adecuada para realizar un cierto tipo de tarea: procesamiento de imágenes, es decir, para llevar a cabo cualquier tipo de operaciones en matrices de datos. La GPU hace esto con una paralelización interna completa, gasta menos energía que la CPU y, en algunos casos, incluso la supera en velocidad absoluta. Finalmente, la GPU y la CPU pueden trabajar en paralelo, cada una en sus propias tareas, proporcionando el máximo rendimiento y / o el mínimo consumo de energía de todo el sistema.
- Ok, Intel. Decidimos usar la GPU Intel para cálculos de propósito general, ¿cómo hacerlo?
- La forma más sencilla que no requiere ningún conocimiento especial en gráficos (sombreadores Direct3D y OpenGL) es OpenCL.
Los núcleos OpenCL son independientes de la plataforma y se ejecutarán automáticamente en todos los dispositivos informáticos disponibles en el sistema: CPU, GPU, FPGA, etc. Pero la tarifa por tal versatilidad está lejos del máximo rendimiento posible en cada tipo de dispositivo, y especialmente en la GPU Intel integrada. Aquí podemos dar un ejemplo: al ejecutar código en cualquier GPU Intel que transponga una matriz de bytes de 16x16, ¡la ventaja de rendimiento de la programación directa de la GPU Intel será 8 veces mayor que con la versión OpenCL!
Además, algunas de las funcionalidades requeridas para implementar algoritmos comunes (por ejemplo, "filtros anchos" que usan datos de un gran grupo de píxeles en una sola transformación), OpenCL simplemente no es compatible.
Por lo tanto, si necesita una velocidad máxima en la GPU y / o algo más complicado que trabajar de forma independiente con cada elemento de la matriz y sus vecinos más cercanos, Intel C for Metal (ICM), una herramienta para desarrollar aplicaciones que se ejecutan en Intel Graphics, lo ayudará .
ICM: ¡bienvenido a la fragua!
Desde el punto de vista del rendimiento y la funcionalidad, ICM puede considerarse "ensamblador de tarjetas gráficas Intel" y, en términos de circuitos y usabilidad, "análogo de OpenCL para tarjetas gráficas Intel".
Durante muchos años, Intel ha utilizado ICM internamente en el desarrollo de productos de procesamiento de medios en la GPU Intel. Pero en 2018, ICM se lanzó al público, ¡e incluso con código abierto!
Intel C for Metal obtuvo su nombre actual hace unos meses, antes de eso se llamaba Intel C for Media (el mismo acrónimo ICM o solo CM o incluso Cm), e incluso antes, el Marco de desarrollo de medios (MDF). Entonces, si en algún lugar del nombre del componente, en la documentación o en los comentarios de código abierto, los nombres antiguos se encuentran, no se alarme, este es un valor histórico.
Entonces, el código de la aplicación ICM, al igual que en OpenCL, contiene dos partes: la "administrativa", ejecutada en el procesador, y el núcleo, ejecutado en la GPU. No es sorprendente que la primera parte se llame host, y la segunda es el kernel.
Los núcleos son una función de procesar un bloque de píxeles dado (o solo datos), se escriben en el lenguaje Intel C para Metal y se compilan en el conjunto de instrucciones Intel GPU (ISA) utilizando el compilador ICM.
El host es una especie de "administrador del equipo de kernel", administra el proceso de transferencia de datos entre la CPU y la GPU y realiza otro "trabajo administrativo" a través de la biblioteca de tiempo de ejecución ICM Runtime y el controlador de medios Intel GPU.
Un flujo de trabajo detallado de ICM se ve así:
- El código de host ICM es compilado por cualquier compilador x86 C / C ++ junto con toda la aplicación;
- El compilador ICM compila el código del núcleo ICM en un archivo binario con algún conjunto de instrucciones comunes (ISA común);
- En tiempo de ejecución, este conjunto general de instrucciones JIT se traduce en una GPU Intel específica;
- El host ICM invoca la biblioteca de tiempo de ejecución ICM para comunicarse con la GPU y el sistema operativo.
Un par de puntos más importantes y útiles:
- Las superficies utilizadas en ICM para representar / almacenar datos se pueden compartir con DirectX 11 y 9 (DXVA en Linux).
- La GPU puede tomar y escribir datos tanto de la memoria de video como de la memoria del sistema compartida con la CPU. ICM incluye funciones especiales para ambos casos de transferencia de datos en ambas direcciones. Al mismo tiempo, la memoria del sistema se comparte exactamente y no se requiere una copia real en ella; para esto, la llamada copia cero se proporciona en ICM.
ICM - en el respiradero del volcán!
Ya del propio nombre "C for Iron", se deduce que el dispositivo de lenguaje corresponde al dispositivo gráfico interno de Intel. Es decir, tiene en cuenta el hecho de que el código se ejecutará en varias decenas de unidades de ejecución de la tarjeta gráfica, cada una de las cuales es un procesador completamente vectorial capaz de ejecutar varios subprocesos simultáneamente.
El lenguaje ICM en sí mismo es C ++ con algunas limitaciones y extensiones. En comparación con C ++, ICM carece de ... punteros, asignación de memoria y variables estáticas. Bajo la prohibición también funciones recursivas. Pero hay una programación explícita del modelo vectorial (SIMD): tipos de datos vectoriales: vector, matriz y superficie; operaciones de vector en estos tipos de datos, condiciones de vector si / si no, realizadas independientemente para cada elemento del vector; así como funciones integradas para acceder a la funcionalidad fija del hardware de la GPU Intel.
El trabajo con vectores, matrices y superficies en tareas reales se ve facilitado por objetos de "subconjuntos": de los objetos básicos correspondientes puede elegir solo los bloques de "referencia" que le interesen o, como caso especial, elementos individuales por máscara.
Por ejemplo, veamos el código ICM que implementa un filtro lineal, reemplazando un valor
Colores RGB de cada píxel por su valor promedio y 8 vecinos en la imagen:
Si los colores (datos) en la matriz están ubicados como
R8G8B8 , el cálculo con la división de la imagen de entrada en bloques de 6x8 píxeles (elementos de datos de 6x24 bytes) será el siguiente:
_GENX_MAIN_ void linear(SurfaceIndex inBuf, SurfaceIndex outBuf, uint h_pos, uint v_pos){
- El tamaño de las matrices se establece en la forma <tipo de datos, alto, ancho>;
- el operador select <v_size, v_stride, h_size, h_stride> (i, j) devuelve la submatriz que comienza con el elemento (i, j) , v_size muestra el número de filas seleccionadas, v_stride - la distancia entre las filas seleccionadas h_size - el número de columnas seleccionadas, h_stride - la distancia entre ellas .
Tenga en cuenta que el tamaño de la matriz de entrada de 8x32 se elige porque aunque el bloque de 8x30 es algorítmicamente suficiente para calcular los valores de todos los píxeles en el bloque de 6x24, el bloque de datos se lee en ICM, no en bytes, sino en elementos dword de 32 bits.
El código anterior es, de hecho, un núcleo ICM completo. Como se mencionó, será compilado por el compilador ICM en dos etapas (precompilación y posterior traducción JIT). El compilador ICM está construido sobre la base de LLVM y, si lo desea, puede
estudiarlo en las fuentes y crearlo usted mismo .
Pero, ¿qué hace el host ICM? Invoca las funciones de la biblioteca de tiempo de ejecución ICM Runtime que:
- Cree, inicialice y elimine después de usar el dispositivo GPU (CmDevice), así como las superficies que contienen datos de usuario utilizados en los núcleos (CmSurface);
- Trabaje con núcleos: descárguelos de archivos .isa precompilados, prepare sus argumentos e indique la parte de los datos con los que trabajará cada núcleo;
- Crear y administrar la cola de ejecución del kernel;
- Controlan el funcionamiento de los hilos que ejecutan cada núcleo en la GPU;
- Gestionar eventos (CmEvent): objetos de sincronización de la GPU y la CPU;
- Transfiera datos entre la GPU y la CPU, o más bien, entre el sistema y la memoria de video;
- Informar errores, medir el tiempo de funcionamiento de los núcleos.
El código de host más simple se ve así:
Como puede ver, no hay nada complicado en crear y usar núcleos y un host. ¡Todo es simple!
La única dificultad para advertir para poder regresar al mundo real: actualmente en la versión pública de ICM, la única forma de depurar los núcleos es imprimir mensajes. Cómo usarlos correctamente se puede ver en el ejemplo
Hello, World .
ICM: ¡no es metal pesado!
Ahora veamos cómo funciona en la práctica. ICM Developer Kit
está disponible para Windows y Linux , y para ambos sistemas operativos contiene el Compilador ICM, documentación y casos de uso de tutoriales. Una descripción detallada de estos ejemplos de capacitación se
descarga por separado .
Para Linux, el paquete también incluye un controlador de medios en modo de usuario para VAAPI con una biblioteca de tiempo de ejecución ICM Runtime integrada. Para Windows, el controlador de gráficos Intel habitual para Windows funcionará con ICM. La biblioteca de tiempo de ejecución ICM Runtime se incluye en el conjunto dll de este controlador. El paquete ICM incluye solo el archivo de enlace .lib para él. Si el controlador falta en su sistema por algún motivo, se descarga del sitio web de Intel y se garantiza el funcionamiento correcto de ICM en los controladores, a partir de la versión 15.60 - 2017).
El código fuente de los componentes se puede encontrar aquí:
El contenido adicional de esta sección se aplica exclusivamente a Windows, pero los principios generales de trabajar con ICM también son aplicables a Linux.
Para el trabajo "regular" con el paquete ICM, necesitará Visual Studio a partir de 2015 y Cmake a partir de la versión 3.2. Al mismo tiempo, la configuración y los archivos de script de los ejemplos de capacitación están diseñados para VS 2015, para usar versiones más recientes de los archivos VS, deberá estudiar y editar las rutas a los componentes VS usted mismo.
Entonces, conociendo ICM para Windows:
- Descargue el archivo ;
- Desempacarlo;
- Comenzamos (preferiblemente en la línea de comando VS) el script de configuración del entorno setupenv.bat con tres parámetros: la generación de GPU Intel (correspondiente al procesador en el que está integrada la GPU, puede dejarse por defecto: gen9), la plataforma de compilación: x86 \ x64 y la versión DirectX para compartiendo con ICM: dx9 / dx11.
Después de eso, simplemente puede compilar todos los ejemplos de capacitación: en la carpeta de ejemplos, el script
build_all.bat lo hará o generará proyectos para Microsoft Visual Studio; esto
creará el script
create_vs.bat con el nombre de un ejemplo específico como parámetro.
Como puede ver, la aplicación ICM será un archivo .exe con la parte del host y un archivo .isa con la parte de GPU precompilada correspondiente.
Se incluyen varios ejemplos en el paquete ICM, desde el más simple Hello, World, que muestra los principios básicos del funcionamiento de ICM, hasta el bastante complicado: la implementación del algoritmo para encontrar el "flujo máximo - corte mínimo" del gráfico (problema de corte mínimo y corte máximo) utilizado en la segmentación y costura de imágenes .
Todos los estudios de caso de ICM están bien documentados en el código y en la
descripción separada ya mencionada. Se recomienda profundizar en ICM precisamente sobre él, estudiando y ejecutando ejemplos secuencialmente y luego modificándolos para que se ajusten a sus necesidades.
Para una comprensión general de todas las características de ICM existentes, se recomienda encarecidamente que estudie la “especificación”: la descripción de ICM
cmlangspec.html en la
carpeta \ documents \ compiler \ html \ cmlangspec .
En particular, describe la API de las funciones ICM implementadas en el hardware: acceso a los llamados muestreadores de textura (Sampler), un mecanismo para filtrar imágenes de diferentes formatos, así como para evaluar el movimiento (Estimación de movimiento) entre cuadros de video y algunas capacidades de análisis de video.
ICM: ¡ataca mientras hace calor!
Al hablar sobre el rendimiento de las aplicaciones ICM, debe tenerse en cuenta que los estudios de casos incluyen la medición del tiempo de su trabajo, de modo que al ejecutarlos en el sistema de destino y compararlos con sus tareas, puede evaluar la conveniencia de utilizar ICM para ellos.
Y las consideraciones generales sobre el rendimiento de ICM son bastante simples:
- Al descargar cálculos en una GPU, recuerde la sobrecarga de transferir datos de CPU <-> GPU y sincronizar estos dispositivos. Por lo tanto, un ejemplo como Hello, World no es un buen candidato para una implementación de ICM. Pero los algoritmos de visión por computadora, IA y cualquier procesamiento no trivial de matrices de datos, especialmente con un cambio en el orden de estos datos en el proceso o en la salida, son lo que ICM necesita.
- Además, al diseñar un código ICM, es necesario tener en cuenta el dispositivo interno de la GPU, es decir, es aconsejable crear un número suficiente (> 1000) de subprocesos de GPU y cargarlos a todos con trabajo. En este caso, es una buena idea dividir las imágenes para procesarlas en pequeños bloques. Pero la forma específica de particionar, así como la elección de un algoritmo de procesamiento específico para lograr el máximo rendimiento, no es una tarea trivial. Sin embargo, esto se aplica a cualquier forma de trabajar con cualquier GPU (y CPU).
¿Tiene código OpenCL, pero su rendimiento no le agrada? ¿O el código CUDA, pero quieres trabajar en un número mucho mayor de plataformas? Entonces vale la pena echarle un vistazo a ICM.
ICM es un producto vivo y en evolución. Puede participar en su uso y su desarrollo: los repositorios correspondientes en github están esperando sus confirmaciones. Toda la información necesaria para ambos procesos se encuentra en este artículo y en los archivos léame en github. Y si falta algo, aparecerá después de sus preguntas en los comentarios.