НИУ ВШЭ СПб ОП ПАДИИ

Применение ML в компиляторах

Литвинов Михаил

@litvinovmitch11

Выполнил работу:

@kpdev42

Ментор:

Косов Павел

План рассказа

  • Введение в тему

План рассказа

  • Введение в тему

  • Исследовательская часть работы

План рассказа

  • Введение в тему

  • Исследовательская часть работы

  • Прикладная часть работы

План рассказа

  • Введение в тему

  • Исследовательская часть работы

  • Прикладная часть работы

  • Выступления на конференциях

План рассказа

  • Введение в тему

  • Исследовательская часть работы

  • Прикладная часть работы

  • Выступления на конференциях

  • Заключение и дальнейшие планы

Начинаем!

Что такое компилятор?

C++

Исполняемый файл

int main(int argc, const char **argv) {

  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  // Initialize targets for clang module support.
  llvm::InitializeAllTargets();

  auto ExpectedParser =
      CommonOptionsParser::create(argc, argv, ClangCheckCategory);

  if (!ExpectedParser) {
      llvm::errs() << ExpectedParser.takeError();
      return 1;
  }
  ...
}
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0xe143f0
  Start of program headers:          64 (bytes into file)
  ...

Что такое компилятор?

Исполняемый файл

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0xe143f0
  Start of program headers:          64 (bytes into file)
  ...

C++

int main(int argc, const char **argv) {

  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  // Initialize targets for clang module support.
  llvm::InitializeAllTargets();

  auto ExpectedParser =
      CommonOptionsParser::create(argc, argv, ClangCheckCategory);

  if (!ExpectedParser) {
      llvm::errs() << ExpectedParser.takeError();
      return 1;
  }
  ...
}

Что такое компилятор?

Исполняемый файл

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              DYN (Position-Independent Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0xe143f0
  Start of program headers:          64 (bytes into file)
  ...

ОПТИМИЗИРУЮЩИЙ?

C++

int main(int argc, const char **argv) {

  llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);

  // Initialize targets for clang module support.
  llvm::InitializeAllTargets();

  auto ExpectedParser =
      CommonOptionsParser::create(argc, argv, ClangCheckCategory);

  if (!ExpectedParser) {
      llvm::errs() << ExpectedParser.takeError();
      return 1;
  }
  ...
}

Что такое компилятор?

С, C++, Rust, ...

LLVM IR

Program analysis

Transform & optimize

CodeGen

ARM, X86, ...

Что такое трансформация?

Clang

С++

LLVM IR

INFO

OPT

CodeGen

ARM, X86

Opt

LLVM - PASS

Pipelines (O1-O3, Os, Oz)

Удаление неиспользуемого кода

Простейший вид CFG

Control Flow Graph

NODE №1

NODE №2

NODE №3

NODE №4

Граф потока управления

Удаление неиспользуемого кода

Простейший вид CFG

Control Flow Graph

Граф потока управления

Заметим, что в NODE №3 никак не попасть

NODE №1

NODE №2

NODE №3

NODE №4

Удаление неиспользуемого кода

Простейший вид CFG

Control Flow Graph

Граф потока управления

Заметим, что в NODE №3 никак не попасть - ее можно не генерировать.

NODE №1

NODE №2

NODE №4

Удаление неиспользуемого кода

Простейший вид CFG

Control Flow Graph

Граф потока управления

- Упростили граф

- Уменьшили codesize

- Уменьшили время компиляции

NODE №1

NODE №2

NODE №4

Примеры посложнее

Оптимизации - это трансформации

Примеры посложнее

Оптимизации - это трансформации

Трансформации - это функции

Примеры посложнее

Оптимизации - это трансформации

Трансформации - это функции

У функций есть гиперпараметры

Примеры посложнее

Оптимизации - это трансформации

Трансформации - это функции

У функций есть гиперпараметры

А вот настроить эти гиперпараметры - поможет ML!

Phase ordering problem

В компиляторе большое число (>100) независимых трансформаций.

 

От порядка выполнения трансформаций зависит результат.

PASS 1

PASS 2

PASS 3

PASS 4

PASS 1

PASS 2

PASS 3

PASS 4

PASS 1

PASS 2

PASS 3

PASS 4

PASS 1

PASS 2

PASS 3

PASS 4

Phase ordering problem & ML

Выбор наилучшей последовательности - NP полная задача.

 

Существуют дефолтные пайплайны, написанные экспертами, но они хороши лишь В СРЕДНЕМ.

 

На помощь приходит RL!

PASS 1

PASS 2

PASS 3

PASS 4

PASS 1

PASS 2

PASS 3

PASS 4

PASS 1

PASS 2

PASS 3

PASS 4

PASS 1

PASS 2

PASS 3

PASS 4

Inlinig

for (size_t i = 0; i < n; ++i) {
	f(i, v);
}

Инлайнинг - встраивание тела функции, вместо ее вызова

uint32_t f(size_t idx, vector<int> &v) {
	v[idx] = 42;
}

Inlinig

for (size_t i = 0; i < n; ++i) {
	f(i, v);
}

Инлайнинг - встраивание тела функции, вместо ее вызова

uint32_t f(size_t idx, vector<int> &v) {
	v[idx] = 42;
}

Inlinig

for (size_t i = 0; i < n; ++i) {
	f(i, v);
}

Инлайнинг - встраивание тела функции, вместо ее вызова

uint32_t f(size_t idx, vector<int> &v) {
	v[idx] = 42;
}
for (size_t i = 0; i < n; ++i) {
	v[i] = 42;
}

Inlinig

for (size_t i = 0; i < n; ++i) {
	f(i, v);
}

Инлайнинг - встраивание тела функции, вместо ее вызова

uint32_t f(size_t idx, vector<int> &v) {
	v[idx] = 42;
}
for (size_t i = 0; i < n; ++i) {
	v[i] = 42;
}

Теперь можно применить другие оптимизации

Inlinig & ML

Сейчас решение о необходимости встраивать функции компилятор принимает на основе различных эвристик (бюджет инлайнинга и др.)

Ручные формулы можно заменить на ML алгоритм, который выдедет наилучшую формулу инлайнинга в конкретном коде, а также сможет сам выделять признаки.

Исследовательская часть

Исследовательские цели

  • Изучение фреймворков, предлагающих инструментарий для применения ML в компиляторах

Исследовательские цели

  • Изучение фреймворков, предлагающих инструментарий для применения ML в компиляторах

  • Популяризация ML методов в компиляторах, путем публичных выступлений

Исследовательские задачи

  • Изучить статьи, конференции и исследования по теме

Исследовательские задачи

  • Изучить статьи, конференции и исследования по теме

  • Выбрать 3 наиболее популярных проекта

Исследовательские задачи

  • Изучить статьи, конференции и исследования по теме

  • Выбрать 3 наиболее популярных проекта

  • Запустить их "из коробки"

Исследовательские задачи

  • Изучить статьи, конференции и исследования по теме

  • Выбрать 3 наиболее популярных проекта

  • Запустить их "из коробки"

  • Оценить проекты по различным метрикам

Исследовательские задачи

  • Изучить статьи, конференции и исследования по теме

  • Выбрать 3 наиболее популярных проекта

  • Запустить их "из коробки"

  • Оценить проекты по различным метрикам

  • Оценить проекты по готовности к продакшену

Исследовательские задачи

  • Изучить статьи, конференции и исследования по теме

  • Выбрать 3 наиболее популярных проекта

  • Запустить их "из коробки"

  • Оценить проекты по различным метрикам

  • Оценить проекты по готовности к продакшену

  • Выступить на конференциях

CompilerGym - Facebook Research

Окружение для циклических алгоритмов обучения с подкреплением (GYM)

Решает задачу - 

Phase Ordering Problem

ML-LLVM - IITH - POSET-RL

Эмбединги кода - IR2Vec

 

Метрика - не только CodeSize,

но и Performance

 

Часть проекта ML-LLVM

С помощью RL решает задачу - 

Phase Ordering Problem

ML-LLVM - IITH - Loop Distribution

Часть проекта ML-LLVM

 

С помощью RL решает задачу - 

Распределения циклов

ML-LLVM - IITH - Rl4ReAl 

Часть проекта ML-LLVM

С помощью RL решает задачу - Аллокации регистров

38/61

MLGO - Google Research - RegAlloc

MLGO создали RegAlloc Advisor - специальный советник,

который предсказывает с помощью ML распределение регистров и помогает избрать лучшее распределение с целью увеличения perfomance.

Главное отличие от IITH - это интегрировано в основной LLVM-project!

MLGO - Google Research - Inlinig

    Стоимость инлайнинга - число, для каждого вхождения функции, определяющее стоимость ее инлайнинга.

Расчет стоимости инлайнинга зависит от некотрых эвристик.

MLGO призван обучить ML модель, чтобы не изобретать формулы стоимостей инлайнинга.

    Бюджет инлайнинга - число, определяющее какую сумму можно потратить на инлайнинг.

Метрики

  • Профит (CodeSize, Performance)

Метрики

  • Профит (CodeSize, Performance)

  • Дополнительное время компиляции

Метрики

  • Профит (CodeSize, Performance)

  • Дополнительное время компиляции

  • Сложность использования ~ Готовность к продакшену

Метрики

  • Профит (CodeSize, Performance)

  • Дополнительное время компиляции

  • Сложность использования ~ Готовность к продакшену

  • Сложность обучения моделей

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 4 потоках: ~ 1 час

Размер директории  ./bin:                  3.560 G

clang - 190.6 Mb

LLVM-18 -O3

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 16 потоках: ~ 1 день

Размер директории  ./bin:                  3.7772 G

clang - 203.16 Mb

CompilerGym RandomSearch - 1000 steps

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 16 потоках: ~ 1 день

Размер директории  ./bin:                  3.7772 G

clang - 203.16 Mb

CompilerGym RandomSearch - 1000 steps

Фокус не удался(

CompilerGym необходимо настраивать, из коробки не работает

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 16 потоках: ~ 1 день, но на больших файлах - fallback

Размер директории  ./bin:                  3.536 G

clang - 186.06 Mb

PosetRL -O3

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

PosetRL -O3

Фокус удался!

Из коробки получили прирост в codesize для O3 ~ 1.004

Время компиляции при 16 потоках: ~ 1 день, но на больших файлах - fallback

Размер директории  ./bin:                  3.536 G

clang - 186.06 Mb

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 4 потоках: ~ 1 час

Размер директории  ./bin:                  4.381 G

clang - 219.65 Mb

LLVM-18 -Oz

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 4 потоках: ~ 1 час

Размер директории  ./bin:                  3.832 G

clang - 196.45 Mb

MLGO Inlinig -Oz

Сравнение всех решений - сборка LLVM

Дефолтная сборка LLVM

Время компиляции при 4 потоках: ~ 1 час

Размер директории  ./bin:                  3.832 G

MLGO Inlinig -Oz

Фокус удался!

Из коробки получили прирост в codesize для Oz ~ 1.143

Время компиляции при 4 потоках: ~ 1 час

Размер директории  ./bin:                  3.832 G

clang - 196.45 Mb

Таблица сравнений

Фреймворк Профит "из коробки" Оверхед компиляции Готовность к продакшену Сложность обучения 
CompilerGym Плохо х25 Да, но сильно доделывать Легко
IITH - ML-LLVM Нормально х60 Сложно судить, пока не очень Нормально
MLGO Отлично Нет Да Нормально

Прикладная часть

Прикладные цели

  • Оценить перспективы доработки MLGO

Прикладные цели

  • Оценить перспективы доработки MLGO

  • И если перспективы есть - доработать фреймворк, так как предпосылки были (CPP RUSSIA 2022)

Прикладные задачи

  • Обучить модель MLGO

Прикладные задачи

  • Обучить модель MLGO

  • Интерпретировать веса признаков

Прикладные задачи

  • Обучить модель MLGO

  • Интерпретировать веса признаков

  • Сравнить со стандартной моделью

Прикладные задачи

  • Обучить модель MLGO

  • Интерпретировать веса признаков

  • Сравнить со стандартной моделью

  • Доработать модель MLGO путем различных экспериментов

Обучение модели MLGO

  • Выбор модели -  inlining for size

Обучение модели MLGO

  • Выбор модели -  inlining for size

  • Выбор алгортма - PPO (Proximal Policy Optimization)

Обучение модели MLGO

  • Выбор модели -  inlining for size

  • Выбор алгортма - PPO (Proximal Policy Optimization)

  • Выбор датасета (корпуса) - llvm-project

Графики обучения

  • Обучение длилось ~1 день на CPU

  • Удалось улучшить стандартный инлайнер примерно на 6%

Интерпретация весов

  • cost_estimate - предполагаемая стоимость инлайнинга

  • callee_users - сколько раз функция используется

  • node_count - количество узлов в графе

Сравнение моделей

Фреймворк Результат Профит
Дефолтный инлайнер 3.2G (3349132)    ./bin/ Стандартно
Инлайнер на новом корпусе 3.1G (3235508)    ./bin/ Нормально
Инлайнер MLGO 3.1G (3173896)    ./bin/ Нормально

Доработки и мысли о будущем

  • Новые алгоритмы - альтернативы PPO

Доработки и мысли о будущем

  • Новые алгоритмы - альтернативы PPO
  • Новые признаки - извлечение фичей из IR

Доработки и мысли о будущем

  • Новые алгоритмы - альтернативы PPO
  • Новые признаки - извлечение фичей из IR

  • Поддержка IR2Vec

Доработки и мысли о будущем

  • Новые алгоритмы - альтернативы PPO
  • Новые признаки - извлечение фичей из IR

  • Поддержка IR2Vec

  • Поддержка пропатченной модели в LLVM

Выступления

CPP RUSSIA 2025

C++ Russia — конференция по разработке на C++. Она сосредоточена на хардкорных докладах: не на общих рассуждениях, а на технической конкретике.

  • 45 спикеров

  • 35 докладов

  • 10 партнеров

  • 600 участников

CPP RUSSIA 2025 - Фотографии

СТАЧКА ВЕСНА-2025

XIII Международная

IT-конференция

  • 250+ докладов

  • 2200+ участников

СТАЧКА ВЕСНА-2025 - Фотографии

The end!

Литвинов Михаил

@litvinovmitch11

Доклад СТАЧКА

Доклад CPP RUSSIA

Моя модель на HF

Ссылки (исследовательская часть)

Ссылки (прикладная часть)

Предобученная модель для LLVM-project - https://huggingface.co/litvinovmitch11/mlgo-llvm-project-pretrained

Логи tesorboard -

https://github.com/litvinovmitch11/mlgo-llvm-project-pretrained

 

The end!

Литвинов Михаил

@litvinovmitch11

Доклад СТАЧКА

Доклад CPP RUSSIA

Моя модель на HF

НИУ ВШЭ СПб НИР "Применение ML в компиляторах"

By Michael Litvinov

НИУ ВШЭ СПб НИР "Применение ML в компиляторах"

  • 55