Resumen de compiladores de aprendizaje profundo

       El desarrollo del aprendizaje profundo ha tenido un profundo impacto en varios campos de la ciencia. No solo ha demostrado un valor significativo en los campos de la inteligencia artificial, como el procesamiento del lenguaje natural (NLP) y la visión artificial (CV), sino que también ha logrado un gran éxito en áreas de aplicación más amplias, como el comercio electrónico, las ciudades inteligentes y el descubrimiento de fármacos. Con la aparición de varios modelos de aprendizaje profundo, como la red neuronal convolucional (CNN), la red neuronal recurrente (RNN), la memoria a corto plazo (LSTM) y la red antagónica generativa (GAN), la programación de varios modelos DL se simplifica a darse cuenta de que su adopción generalizada es fundamental.

        Con los esfuerzos continuos de la industria y la academia, se han propuesto algunos marcos de DL populares, como TensorFlow, PyTorch, MXNet y CNTK, para simplificar la implementación de varios modelos de DL. Aunque los marcos de DL anteriores tienen sus ventajas y desventajas de acuerdo con las ventajas y desventajas de su diseño, la interoperabilidad se vuelve muy importante para reducir los esfuerzos de ingeniería redundantes cuando se admiten modelos de DL emergentes en modelos de DL existentes. Para proporcionar interoperabilidad, se propone ONNX, que define un formato unificado para representar modelos DL para facilitar la conversión de modelos entre diferentes marcos DL.

       Para abordar las deficiencias de las bibliotecas y herramientas de DL y aliviar la carga de optimizar manualmente los modelos de DL en cada hardware de DL, la comunidad de DL está promoviendo el desarrollo de compiladores específicos de dominio. La industria y la academia han propuesto varios compiladores DL populares, como TVM, Tensor Comprehension, Glow, nGraph y XLA. Un compilador de DL toma la definición del modelo descrita en el marco de DL como entrada y genera implementaciones de código eficientes en varios hardware de DL como salida. La conversión entre la definición del modelo y la implementación del código concreto está altamente optimizada para la especificación del modelo y la arquitectura de hardware. Específicamente, incorporan optimizaciones orientadas a DL, como la fusión de capas y operadores de operación (como Conv+BatchNorm), lo que hace que la generación de código sea más eficiente. Además, los compiladores DL existentes también aprovechan cadenas de herramientas maduras de compiladores de propósito general como LLVM, que brindan una mejor portabilidad en diferentes arquitecturas de hardware. Al igual que los compiladores tradicionales, los compiladores DL también adoptan un diseño en capas de front-end, código intermedio y back-end. Sin embargo, la singularidad de los compiladores de DL radica en el diseño de IR multinivel y optimizaciones específicas de DL.

  • Marco de aprendizaje profundo

Figura 1. Marco de aprendizaje profundo

La Figura 1 muestra la perspectiva de los marcos DL, incluidos los marcos populares actuales, los marcos históricos y los marcos compatibles con ONNX.

TensorFlow : entre todos los marcos de DL, TensorFlow tiene el soporte más completo para interfaces de lenguaje, incluidos C++, Python, Java, Go, R y Haskell. Para reducir la complejidad del uso de TensorFlow, Google adoptó Keras como la interfaz del núcleo de TensorFlow.

Keras : una biblioteca de redes neuronales de alto nivel para construir rápidamente modelos DL, escrita en Python puro. Aunque Keras en sí no es un marco DL, proporciona una API de alto nivel que se integra con TensorFlow, MXNet, Theano y CNTK. Con Keras, los desarrolladores de DL pueden crear una red neuronal con solo unas pocas líneas de código. Sin embargo, Keras no es lo suficientemente flexible debido a la sobreencapsulación, lo que hace que sea muy difícil agregar operadores u obtener información de datos de bajo nivel.

PyTorch : Facebook lanzó PyTorch reescribiendo el framework DL basado en Lua Torch en Python y refactorizando todos los módulos en el nivel Tensor. Como el marco dinámico más popular, PyTorch incorpora primitivas en Python para crear gráficos de flujo de datos dinámicos, donde el flujo de control se ejecuta en el intérprete de Python. PyTorch 1.0 integra el código base de PyTorch 0.4 y Caffe2 para crear un marco unificado. Esto permite que PyTorch absorba las ventajas de Caffe2 para respaldar la ejecución eficiente de gráficos y la implementación móvil.

Caffe/Caffe2 : Caffe fue diseñado por UC Berkeley para aprendizaje profundo y clasificación de imágenes. Caffe tiene API para línea de comandos, Python y matlab. La simplicidad de Caffe hace que el código fuente sea fácil de expandir y adecuado para un análisis en profundidad por parte de los desarrolladores. Por lo tanto, Caffe está orientado principalmente a la investigación, lo que lo ha hecho popular desde el principio hasta el día de hoy. Caffe2 se basa en el proyecto original de Caffe. Caffe2 es similar a TensorFlow en estructura de código, aunque su API es más liviana y es más fácil acceder a resultados intermedios en el gráfico de cálculo.

MXNET : MXNET admite varias API de lenguaje, incluidos Python, C++, R, Julia, Matlab y JavaScript. Está diseñado para la escalabilidad y diseñado desde la perspectiva de reducir la carga de datos y la complejidad de E/S. MXNet ofrece diferentes paradigmas: programación declarativa como caffe y Tensorflow y programación imperativa como PyTorch. CNTK : disponible a través de API en Python y C++, o puede usar su propio lenguaje de secuencias de comandos (es decir, BrainScript). CNTK está diseñado para ser fácil de usar y producir, listo para datos a gran escala en producción. Utiliza un gráfico computacional estático similar a TensorFlow y Caffe, donde un modelo DL se ve como una serie de pasos computacionales a través de un gráfico dirigido.

Pádel-Pádel : El diseño original es similar a Caffe, donde cada modelo se puede representar como un conjunto de capas. Sin embargo, Paddle-Paddlev2 hace referencia al concepto de operador de TensorFlow, que descompone las capas en operadores más detallados, lo que admite modelos DL más complejos. Y paddle Fluid es similar a PyTorch en que proporciona su propio intérprete, evitando así el rendimiento limitado del intérprete de Python.

ONNX : Open Neural Network Exchange (ONNX) define un modelo de gráfico computacional escalable, por lo que los gráficos computacionales creados por diferentes marcos DL se pueden convertir fácilmente a ONNX. La conversión de modelos entre marcos DL se vuelve más fácil con ONNX. Por ejemplo, permite a los desarrolladores crear modelos MXNet y luego usar PyTorch para ejecutar los modelos para la inferencia. Como se muestra en la Figura 1, ONNX se ha integrado en PyTorch, MXNet, paddle, etc. Para algunos marcos DL que aún no son compatibles directamente (como TensorFlow y Keras), ONNX les agrega convertidores.

Marcos obsoletos: debido al rápido desarrollo de la comunidad de DL, muchos marcos de DL históricos ya no están activos. Por ejemplo, PyTorch ha reemplazado a Torch. Como uno de los marcos de DL más antiguos, Theano ya no se mantiene. Chainer solía ser el marco elegido para gráficos computacionales dinámicos, pero fue reemplazado por MXNet, PyTorch y TensorFlow con características similares.

  • Diseño de arquitectura del compilador de aprendizaje profundo

La arquitectura de diseño general del compilador DL ​​incluye principalmente dos partes: el front-end y el back-end, como se muestra en la Figura 2. El código intermedio (IR) se distribuye entre el frontend y el backend. En general, IR es una abstracción de un programa y se utiliza para la optimización de programas. Específicamente, el modelo DL se transforma en un IR multinivel en un compilador DL, donde el IR de alto nivel reside en el front-end mientras que el IR de bajo nivel reside en el back-end. El front-end del compilador se basa en un IR de alto nivel responsable de las transformaciones y optimizaciones independientes del hardware. Según el IR subyacente, el backend del compilador es responsable de las optimizaciones específicas del hardware, la generación de código y la compilación.

Figura 2. Descripción general de la arquitectura de diseño del compilador DL ​​generalmente adoptada

IR de alto nivel: también conocido como gráfico IR, representa el flujo de cálculo y control, independiente del hardware. El desafío de diseño de IR de alto nivel es la capacidad de abstracción del flujo de control y computación, que puede capturar y representar varios modelos de DL. El objetivo de IR de alto nivel es establecer el flujo de control y las dependencias entre los operadores y los datos, y proporcionar una interfaz para la optimización a nivel de gráfico. También contiene información semántica rica para la compilación y proporciona extensibilidad para operadores personalizados.

IR de bajo nivel: diseñado para la optimización de hardware específico y la generación de código para diferentes objetivos de hardware. Por lo tanto, el IR subyacente debe ser lo suficientemente detallado para reflejar las características del hardware y representar las optimizaciones específicas del hardware. También debería permitir el uso de cadenas de herramientas maduras de terceros como Halide, polyhedral y LLVM en el backend del compilador.

El front-end obtiene un modelo DL del marco DL existente como entrada y luego convierte el modelo en una representación gráfica computacional (como se muestra en IR). El front-end necesita implementar varias conversiones de formato para admitir diferentes formatos en diferentes marcos. La optimización de gráficos computacionales combina técnicas de optimización de compilador de propósito general y técnicas de optimización específicas de DL para reducir la redundancia en gráficos computacionales y mejorar la eficiencia computacional. Esta optimización se puede dividir en nivel de nodo (como eliminación de nop y eliminación de tensor de dimensión cero), nivel de bloque (como simplificación algebraica, fusión de operadores y sumidero de operadores) y nivel de flujo de datos (como CSE, DCE, planificación de memoria estática y transición de diseño). Después del frontend, se genera un gráfico computacional optimizado y se pasa al backend.

El backend convierte IR de alto nivel en IR de bajo nivel y realiza optimizaciones específicas de hardware. Por un lado, puede convertir directamente IR de alto nivel en cadenas de herramientas de terceros (como LLVM IR) para aprovechar la infraestructura existente para la optimización de propósito general y la generación de código. Por otro lado, puede aprovechar el modelo DL y el conocimiento previo de las características del hardware para generar código de manera más eficiente a través de un proceso de compilación personalizado. Las optimizaciones de hardware comunes incluyen mapeo interno de hardware, asignación y adquisición de memoria, ocultación de latencia de memoria, paralelización y optimización orientada a bucles. Para determinar la configuración de parámetros óptima en un gran espacio de optimización, los compiladores DL existentes generalmente adoptan dos métodos: programación automática (como poliédrica) y ajuste automático (como AutoTVM).

Supongo que te gusta

Origin blog.csdn.net/lily_19861986/article/details/131451815
Recomendado
Clasificación