Экосистема TensorFlow содержит ряд компиляторов и оптимизаторов, работающих на различных уровнях программного и аппаратного стека. Для тех, кто использует Tensorflow ежедневно, этот многоуровневый стек может порождать трудные для понимания ошибки, как времени компиляции, так и в рантайме, связанные с использованием разного рода железа (GPU, TPU, мобильных платформ и пр.)

Эти компоненты, начиная с графа Tensorflow, могут быть представлены в виде такой диаграммы:



На самом деле всё сложнее

На этой диаграмме мы можем видеть, что графы Tensorflow могут быть запущены несколькими разными способами

примечание
В TensorFlow 2.0, графы могут быть неявными, жадное исполнение может запускать операции индивидуально, по группам, или на полном графе. Эти графы или фрагменты графа должны быть оптимизированы и выполнены.

Например: 

  • Посылаем графы исполнителю Tensorflow, который вызывает написанные вручную специализированные ядра
  • Преобразуем их в XLA HLO (XLA High-Level Optimizer representation) — высокоуровневое представление оптимизатора XLA, который, в свою очередь, может вызывать компилятор LLVM для CPU или GPU, или продолжать использовать XLA для TPU, или комбинировать их. 
  • Преобразуем их в TensorRT, nGraph, или другой формат для специализированного набора инструкций, реализованного в железе.
  • Преобразуем их в формат TensorFlow Lite, выполняемый в рантайме TensorFlow Lite, или преобразуемый в код для запуска на GPU или DSP через Android Neural Networks API (NNAPI) или подобным образом.

Также существуют более сложные способы, включающие в себя множество проходов оптимизации на каждом слое, как, например, в фреймворке Grappler, который оптимизирует операции в TensorFlow.

Несмотря на то, что эти различные реализации компиляторов и промежуточных представлений улучшают производительность, их разнообразие представляет проблему для конечных пользователей, такие, как сбивающие с толку сообщения об ошибках при сопряжении этих подсистем. Также создатели новых программных и аппаратных стеков должны подстраивать проходы оптимизации и преобразования для каждого нового случая.

И в силу всего этого, мы рады анонсировать MLIR, Многоуровненвое Промежуточное Представление (Multi-Level Intermediate Representation). Это формат промежуточ��ого представления и библиотеки компиляции, предназначенные для использования между представлением модели и низкоуровневым компилятором, генерирующим аппаратно-зависимый код. Представляя MLIR, мы хотим дать дорогу новым исследованиям в разработке оптимизирующих компиляторов и реализациям компиляторов, построенных на компонентах промышленного качества.

Мы ожидаем, что MLIR будет интересен многим группам, включая:

  • исследователям компиляторов, а также практикам, желающим оптимизировать производительность и потребление памяти моделей машинного обучения;
  • производителям аппаратного обеспечения, ищущим способ объединить с Tensorflow своё железо, такое, как TPU, мобильные нейропроцессоры в смартфонах, и другие кастомные ASIC-и;
  • людям, которые хотят дать языкам программирования преимущества, предоставляемые оптимизирущими компиляторами и аппаратными ускорителями;

Что такое MLIR?


MLIR, по сути, гибкая инфраструктура для современных оптимизирующих компиляторов. Это значит, что она состоит из спецификации промежуточного представления (IR) и набора инструментов для преобразования этого представления. Когда мы говорим о компиляторах, переход от более высокоуровневого представления к более низкоуровневому называется «спуском» (lowering), и мы будем использовать этот термин в дальнейшем.

MLIR построен под влиянием LLVM и беззастенчиво заимствует многие хорошие идеи из него. Он имеет гибкую систему типов, и предназначен для представления, анализа и преобразования графов, объединяя множество уровней абстракции в одном уровне компиляции. Эти абстракции включают в себя операции Tensorflow, вложенные регионы полиэдральных циклов, инструкции LLVM, а также операции и типы с фиксированной точкой.

Диалекты MLIR 


Для того, чтобы разделить различные программные и аппаратные таргеты, MLIR имеет «диалекты», включающие в себя:

  • TensorFlow IR, включающий в себя всё то, что возможно сделать в графах TensorFlow
  • XLA HLO IR, разработанный для того, чтобы получить все преимущества, предоставляемые компилятором XLA, на выходе которого мы можем получит код для TPU, и не только.
  • Экспериментальный аффинный диалект, предназначенный специально для полиэдральных представлений и оптимизаций
  • LLVM IR, 1:1 совпадающий с собственным представлением LLVM, позволяющий MLIR генерировать код для GPU и CPU с помощью LLVM. 
  • TensorFlow Lite, предназначенный для генерации кода для мобильных платформ

Каждый диалект содержит набор определённых операций, с использованием инвариантов, таких, как: «это бинарный оператор, и его вход и выход имеют один и тот же тип».

Расширения MLIR


MLIR не имеет фиксированного и встроенного списка глобальных intrinsic-операций. Диалекты могут определять полностью кастомные типы, и таким образом MLIR может моделировать такие вещи, как систему типов LLVM IR (имеющую агрегаты первого класса), абстракции доменных языков, такие, как квантизованные типы, важные для оптимизированных под ML ускорителей, и, в будущем, даже систему типов Swift или Clang.

Если вы хотите присоединить к этой системе новый низкоуровневый компилятор, вы можете создать новый диалект и спуск с диалекта графа TensorFlow на ваш диалект. Это упрощает путь для разработчиков аппаратного обеспечения и разработчиков компилятора. Вы можете нацелить диалект на различные уровни одной и той же модели, высокоуровневые оптимизаторы будут отвечать за специфические части IR.

Для исследователей компиляторов и разработчиков фреймворков, MLIR позволяет вам создать преобразования на каждом уровне, вы можете определять свои собственные операции и абстракции в IR, позволяя вам лучше моделировать ваши прикладные задачи. Таким образом, MLIR — это нечто большее, чем чистая инфраструктура компилятора, которой является LLVM.

Хотя MLIR работает как компилятор для ML, он также позволяет использовать технологии машинного обучения! Это очень важно для инже��еров, разрабатывающих численные библиотеки, и не могут обеспечить поддержку всего многообразия ML-моделей и аппаратного обеспечения. Гибкость MLIR облегчает исследования стратегий спуска кода при переходе между уровнями абстракции.

Что дальше


Мы открыли GitHub-репозиторий и приглашаем всех заинтересованных (изучите наше руководство!). Мы будем выпускать нечто большее, чем этот набор инструментов — спецификации диалектов TensorFlow и TF Lite, в ближайшие месяцы. Мы можем рассказать вам больше, для того, чтобы узнать подробности, см. презентацию Криса Латтнера и наш README на Github.

Если вы хотите быть в курсе всех вещей, относящихся к MLIR, присоединяйтесь к нашему новому списку рассылки, который в ближайшее время будет сфокусирован на анонсах будущих релизов нашего проекта. Оставайтесь с нами!