Системное программирование и разработка процессоров — область достаточно узкая, из-за чего её часто воспринимают как что-то непонятное и недоступное. Хотим поделиться новым подкастом «Битовые маски», который планирует исправить это впечатление. В каждом выпуске будем общаться с инженерами, причастными к созданию продуктов, которыми многие программисты пользуются ежедневно, и разбирать с ними интересные нюансы, мифы и задачи отрасли.
Гостем первого эпизода стал Дмитрий Петров, писавший компилятор для Kotlin. Для тех, кто не любит слушать — расшифровка ряда интересных фрагментов ниже. Мы очень хотим фидбека: не стесняйтесь писать в комментарии или личные сообщения.
Мы уже записываем новые эпизоды — подписывайтесь на ютуб-плейлист, чтобы не пропустить. Вскоре «Битовые маски» появятся и на других платформах.
«Наверно, я сейчас ближе к бэкенду. Но это вообще не то, о чем ты думаешь»
Елена Лепилкина, соавтор подкаста: Меня всегда веселит, когда человек что-то знает о программировании и спрашивает: «Чем ты занимаешься? Бэкенд или фронтенд?».
Антон Афанасьев, соавтор подкаста: Да, думаю, для многих бэкенд и фронтенд — это термины из области веб-разработки. В нашем мире обычно компилятор делят на три крупные части: фронтенд, миддленд и бэкенд. Насколько легко системному программисту переходить из фронтенда в бэкенд или миддленд? Есть какие-то границы?
Дмитрий Петров: По-разному, и обычно зависит от того, насколько большая команда занимается этим компилятором.
Дмитрий Петров, ведущий разработчик компиляторной команды Syntacore
20+ лет создает системное ПО. Разрабатывал С/С++ компилятор в МЦСТ, Kotlin-компилятор в JetBrains, работал в Intel Labs. Сейчас разрабатывает компилятор C/C++ для RISC-V архитектуры.
В каждой из этих областей решают свои задачи. Пример интересных задач во фронтенде — вывод типов или разрешение перегрузок, которые связаны с выводом типов. В миддленде это различные высокоуровневые оптимизации, например, преобразование над циклами. В бэкенде — низкоуровневые, скажем, статическое планирование выполнения инструкций.
У них одни и те же общие принципы, но работа разная чисто технически. Бэкендеры обычно гораздо сильнее зарываются в тонкие особенности целевой платформы, хотя в миддленде это тоже важно.
«Очень мало кто обращает внимание на это, когда пишет код приложения» — проблема параллелизма на уровне инструкций
Антон Афанасьев: Что такое instruction scheduling?
Дмитрий Петров: Это попытка на уровне компиляции так расположить инструкции, чтобы извлечь максимум из вычислительных ресурсов процессора. В том числе этим я как раз занимаюсь.
Елена Лепилкина: Обычно здесь есть ограничения по памяти. Можно ли всё переставить эффективно?
Дмитрий Петров: Конечно нет.
Довольно часто у компилятора бывают связаны руки, потому что очень мало кто обращает внимание на такие подробности, когда пишет код приложения.
Например, компилятор не всегда может сделать вывод, что два указателя указывают на непересекающиеся области памяти. В таком случае он всегда сделает оптимизацию из консервативных предположений о том, что эти операции читают или пишут что-то, что может пересекаться. Эти операции зависимы, и их никак нельзя переупорядочивать, даже если компилятор счёл бы это более выгодным, потому что это просто нарушит семантику исполнения программы.
Елена Лепилкина: Чтобы оценить стоимость этих инструкций и расписание нужна информация. Как она собирается? Есть ли у разработчиков компиляторов лучшие практики, чтобы построить cost-модель?
Дмитрий Петров: Если мы имеем доступ к документации по целевому процессору, нужно посмотреть в неё. Но и тут доверяй, но проверяй: если процессор находится в разработке, документация может не поспевать за его реальным состоянием.
Тогда можно использовать инструменты, которые позволяют экспериментальным путем оценить, сколько времени занимает та или иная инструкция. Такой инструмент, в частности есть во фреймворке LLVM — llvm-exegesis.
Если у нас есть доступ к исходному коду процессора, то можно собрать его симулятор из Verilog и посмотреть трассы исполнения. Обладая таким «рентгеновским зрением» и полным знанием о том, что происходит, можно взять и сказать: «Пять тактов».
Наконец, иногда мы просто можем задать вопрос разработчикам железа.
Про бизнес-задачи, бенчмарки и откуда они берутся
Дмитрий Петров: Если мы имеем доступ целевым приложениям, которые будут в основном бежать на нашей архитектуре, то для нас главное — не результаты бенчмарков, а то, что будет, например, исполняться в системе хранения данных. Скажем, если мы делаем графический ускоритель, для нас важно, чтобы быстро обсчитывались треугольники. И совершенно не важно, сколько будет занимать coremark на нашей графической карте.
Есть бенчмарки общего назначения для процессоров общего назначения. А есть конкретные жизненные и бизнес-задачи, под которые делаются специальные процессоры или оптимизируются готовые процессоры общего назначения.
И в итоге важно, насколько хорошо реальный клиентский код, скомпилированный этим компилятором, бежит на этом процессоре. Потому что за что клиент платит деньги? За производительность.
Антон Афанасьев: Даже если это 1%.
Дмитрий Петров: Иногда да. 1% — это одна конкретная компиляторная оптимизация. Упорным накоплением 1-5% процентов за раз и происходит оптимизация компиляторов. Ну а если набрать 20 оптимизаций, то вот уже и 20%.
Антон Афанасьев: Я бы ещё умножал этот 1% не только на количество оптимизаций, но и на число людей, которые будут пользоваться этим процентом. У компиляторов тысячи пользователей — а значит, мы можем сэкономить очень много человеко-часов.
Про баги в JVM — байки из времен работы с Kotlin-компилятором и JIT
Антон Афанасьев: Вспомни пример бага, связанного с JVM, с JIT в нём, с тем, как это идет от Kotlin на JVM, и оттуда — на целевую архитектуру?
Дмитрий Петров: Типичный пример — как мы гонялись за JVM-ными оптимизациями конкатенации строк. В JVM от релиза к релизу в HotSpot менялись эвристики того, как JIT оптимизирует конкатенацию строк. Видимо, они подгонялись под всякие бенчмарки, типа SPECjbb.
Антон Афанасьев: То есть JVM распознавал конкатенацию?
Дмитрий Петров: Да. JIT разными своими эвристиками распознавал некоторые паттерны. Он всё знал про конкатенацию, что это метод StringBuilder.append. Но разные паттерны конкатенации строк он компилировал немного с разной производительностью. И мы очень старались сгенерировать код, максимально похожий на то, что делает в этом месте javac, чтобы JIT было полегче.
Это очень специфическая и не главная деталь работы. Но хороший пример того, что есть целевая платформа, у которой очень странные особенности, и за ними нужно все время следить.
Антон Афанасьев: И опять же, документации на нее нет.
Дмитрий Петров: Да. Лучшая документации — это исходный код. И логи JIT.
Если вам понравилось
Предлагаем послушать выпуск полностью: мы также поговорили про инструменты разработки, советы начинающим программистам, разных игроков и продукты в отрасли и как она поменялась за 20+ лет. И подписаться на нас здесь. Мы планруем выпускать по эпизоду в месяц. Выход на других платформах скоро.
Также оставляйте свои комментарии и пожелания по темам под постом — нам важен фидбек!
Об авторах и идее подкаста
Подкаст придумали и ведут Елена Лепилкина и Антон Афанасьев.
Елена Лепилкина, разработчик компиляторной команды Syntacore
Ранее участвовала в разработке С/С++ компилятора на базе LLVM для ARC архитектуры в Synopsys и Kotlin/Native компилятора в JetBrains.
Антон Афанасьев, тимлид компиляторной команды Syntacore
До этого занимался компиляторами в AMD, Intel, Sony.
Название подкаста отсылает к идее ребята в хорошем смысле «срывать маски» с крутых коллег по отрасли — представлять их более широкой аудитории, и через их опыт показать историю развития и крупных игроков в этой сфере, а также различные варианты развития карьеры для системных программистов.
Комментарии (8)
heos_spb
09.06.2023 07:27+10Ну вот вам фидбэк:
расшифровка ряда интересных фрагментов
Никогда больше не делайте такой ерунды. Помимо того, что сказано в комментарии выше, это а) очень грубо и б) очень непрофессионально. Или делайте полную расшифровку, или не делайте вообще.
unreal_undead2
09.06.2023 07:27Обладая таким «рентгеновским зрением» и полным знанием о том, что происходит, можно взять и сказать: «Пять тактов».
Нужна всё таки не одна цифра, а latency/throughput/раскладка по портам, так что под симулятором придётся много бенчмарков прогнать. Можно ли попробовать получить данные анализом верилоговского исходника - по идее информации там достаточно?
Такой инструмент, в частности есть во фреймворке LLVM — llvm-exegesis.
Хотел спросить про портирование на RISCV, но таки погуглил - https://discourse.llvm.org/t/llvm-exegesis-questions/62708 - вопросов больше нет )
mark_ablov
09.06.2023 07:27+1Тема интересная, но для аудио/видео формата мало подходит. Даже если это будет не подкаст, а какой-то монтаж, то придётся хронометраж растягивать и какие-то пояснения/иллюстрации на экране показывать.
vadimr
Замысел публикации хороший, а исполнение отвратительное. Такие вещи бессмысленно воспринимать на слух. Нужен текст.
spasibo_kep
Привет, ну если будет запрос, дорасшифровать и причесать текст всего эпизода можно, хоть это явно и потребует времени и ресурса)
Единственное, отмечу, эпитеты вроде "отвратительно" едва ли добавят ребятам энтузиазма. Будьте мягче к людям, которые делают контент для сообщества.
vadimr
Я не вижу тут контента. Вижу рекламный текст для ролика на ютубе, который явно не буду смотреть, так как это неподходящий формат для таких серьёзных вопросов. Хотелось бы почитать, но текста нет.
И не понимаю, зачем вообще такие вопросы излагать в аудиовизуальной форме, которую надо затем расшифровывать. Наверняка, людям, занимающимся системным программированием, не составляет труда выражать свои мысли сразу в форме текста.
Очень неудачная идея пресс-службы, проистекающая из непонимания особенностей целевой аудитории.