Проекты Центра разработки Intel в России. Intel Integrated Performance Primitives
Наш рассказ об очередном проекте Intel, сделанном в России. Это библиотека Intel Integrated Performance Primitives — набор готовых к употреблению, высоко оптимизированных под различные архитектуры Intel, к тому же совершенно бесплатных базовых функций для работы с изображениями, сигналами и произвольными данными. Каким образом зародился этот проект, как развивался, что происходит в Intel IPP сейчас — в статье под катом. А начнем мы, как это принято в резюме, с современности.
На КДПВ — вход на этаж IPP в офисе Intel в Нижнем Новгороде
Что такое Intel IPP сейчас
Итак, Intel IPP — это кирпичики функциональных примитивов, позволяющие существенно ускорить работу ПО, обрабатывающего медиа и данные, за счет специфичных для конкретных микроархитектур и платформ Intel оптимизаций, а также максимально широкого использования наборов векторных инструкций Intel SSE и Intel AVX всех версий.
Функции IPP покрывают четыре больших домена:
- Обработка изображений;
- Сжатие данных;
- Обработка сигналов;
- Криптография.
Текущая версия Intel IPP 2020 Update 2 содержит более 2 500 примитивов обработки изображений, 1 300 примитивов обработки сигналов, 500 — компьютерного зрения и 300 — криптографии.
Библиотека постоянно совершенствуется — оптимизируется под новые платформы, добавляется новая функциональность и неизбежно удаляется старая, малоиспользуемая.
Intel IPP работает на любом устройстве с х86 архитектурой под управлением Linux, macOS, Windows и Android. То есть, поддерживаются процессоры не только Intel, но и других производителей, причём, работает IPP на них быстро, хотя, конечно, и не так супербыстро, как на устройствах Intel.
При этом пользователям IPP не требуется глубоких знаний о платформе исполнения их кода, использующего IPP, и связанных с этим действий — нужная версия оптимизаций будет вызвана автоматически.
IPP написана на языке Си с использованием так называемых интринсик-функций компилятора. Для разных моделей применения библиотеки имеются различные ее версии: однопоточная для вызовов из разных потоков внешних приложений и многопоточная, использующая эффективное внутреннее распараллеливание.
Для интересующихся скоростью работы на Intel Xeon и Core — некоторые бенчмарки.
В настоящее время IPP доступна в составе Intel Parallel Studio XE, Intel System Studio, и просто сама по себе. И — абсолютно бесплатно для персонального и коммерческого использования.
Интересно, что наиболее «закрытая» область нашей жизни — криптография, в случае IPP сейчас является наиболее открытой — это проект с открытым кодом, доступный на Github.
Тот задел, подход и API, что принёс IPP при своем появлении в обработку сигналов и изображений, сейчас можно назвать негласным стандартом — то же самое касается и криптографии.
Все компоненты библиотеки используются миллионами пользователей в сотнях тысяч приложений по всему миру. В том числе и внутри самой компании — в различных подразделениях Intel. Intel IPP обеспечивает значительное ускорение работы библиотеки OpenCV. Кстати, специальная сборка Intel IPP c функциями, используемыми OpenCV, выпущенная в 2015 году, стала первой бесплатной свободно распространяемой версией IPP.
Intel IPP можно встретить в приложениях для распознавания и улучшения изображений во всех областях, включая медицину; принтерах, в том числе и 3D; цифровом видеонаблюдении; автономных автомобилях; распознавании и синтезе речи; сжатии данных; телекоммуникации и играх. IPP работает везде — от серверов до носимых устройств. Можно утверждать, что если бы была изобретена машина времени, то ее софт обязательно использовал бы Intel IPP.
История IPP
Начиналось всё с библиотек Intel по обработке сигналов (SPL) и обработки изображений (IPL), разрабатывавшихся по заказу Intel в федеральном ядерном центре ВНИИЭФ в Сарове (мы писали про это в рассказе про OpenCV).
В 1996 (или 1997 году по свидетельствам разных очевидцев) в головном офисе Intel Санта Клара прошло совещание по поводу дальнейших планов развития SPL и IPL с участием американских кураторов проекта и приглашенных специалистов из Сарова, среди которых был будущий архитектор, вдохновитель и руководитель команды IPP Борис Сабанин, а также Сергей Кириллов, в настоящее время возглавляющий работу над IPP-криптографией.
Саровская команда привезла свой список предложений, и одним из них было открытие для пользователей интерфейсов низкоуровневых функций IPL и SPL, так как они все равно уже были реализованы и оптимизированы, меж тем некоторым пользователям форматы данных IPL были неудобны, у них в готовых продуктах уже были свои сложившиеся форматы изображений. Предлагаемый прототип интерфейса IPP, использующий более простые в сравнении с IPL/ISL структуры, был создан Борисом Сабаниным в ходе обсуждения буквально на салфетке. Но в то время предложение российской стороны хотя и не было отвергнуто, но и не получило особой поддержки — оно оказалось в середине списка с малым приоритетом. Но через пару лет кто-то в Intel вспомнил об этом (скорее всего, Шин Ли, впоследствии ставший «евангелистом» Intel IPP) и планы поменялись.
Книга про Intel IPP, написанная в 2004 Stewart Taylor, участником исторического совещания по созданию IPP (в то время — только что нанятым в Intel бакалавром Стэнфорда)
Так началась работа над библиотеками Intel Performance Primitives, которые позднее были переименованы в Integrated Performance Primitives.
Внутренний вариант IPP, назовем его 1.0, был создан в 1999 году. Это был скорее Proof of Concept, прототип для подтверждения жизнеспособности концепции. Он не выпускался как продукт, но позволил определить и уточнить концепцию, архитектуру и спецификации IPP. Первая публичная версия сразу носила номер 2.0 и вышла в апреле 2002 года.
Основная часть работ над библиотеками IPP до 2009 года проходила под руководством Бориса Сабанина, которого по праву можно считать крестным отцом и душой IPP. Он вложил в проект много сил, выстроил команду разносторонних специалистов но, к сожалению, немного не дожил до двадцатилетия Intel IPP.
Картина «Мост к саровской башне» авторства Бориса Сабанина, известного не только IPP (здесь можно посмотреть другие картины Сабанина, в том числе его автопортрет)
Но наследием IPL/ISL дело не ограничилось. Практически сразу появились примитивы для криптографии и компрессии данных. Начались эксперименты в области Computer Vision, которые позже переросли в проект с OpenCV, использующий ускорение алгоритмов с помощью примитивов в ippCV домене.
Конечно же, это был не единственный эксперимент и ответвление в истории создания библиотек. IPP шли в ногу со всем Intel. Соответственно, например, пятая версия IPP помимо x86 поддерживала и процессор Intel XScale (ARM архитектура) и Intel Itanium (IA-64)! В разные годы IPP включали такие компоненты как трассировка лучей (realistic rendering), операции с небольшими матрицами (small matrix operations), проверка целостности данных (data integrity), видео и аудио кодеки.
Эту функциональность при желании можно использовать и сейчас — с помощью пакета IPP Legacy Libraries, доступного для скачивания.
Более того, видеокодеки IPP в дальнейшем послужили основой другого известного продукта Intel — Intel Media SDK, а трассировка лучей была реализована в проекте с открытом кодом Intel Embree.
Из интересных технологических опытов в области IPP-строения можно отметить пример Windows-драйвера для демонстрации возможности работы IPP в режиме ядра, а также версию IPP для работы на интегрированных Intel GPU, написанную на C for Metal.
Любопытно, что номера версий IPP сначала шли по порядку от 1 до 9, а потом начали обозначаться годом выхода — 2017–2020.
Команда разработчиков Intel IPP в 2003 году
За время существования семейства библиотек IPP в работе над ними принимало участие более 100 человек — в Сарове, Нижнем Новгороде и Москве. Сейчас штаб-квартира IPP находится в Нижнем Новгороде и выглядит очень привлекательно!
Оформление этажа IPP в Intel
IPP — совсем не примитивная библиотека!
Хотя в названии Intel IPP и есть слово «примитив», да и на первый взгляд, никаких принципиальных сложностей в наборе «деталей конструктора» для создания производительных программ, которым по сути является IPP, быть не может, устройство этих библиотек совсем не тривиально. Для обеспечения максимальной производительности и удобства использования IPP применены интересные технологические решения.
Как уже было сказано, в IPP содержатся тысячи функций (а каждая функция имеет несколько версий, оптимизированных под конкретную архитектуру), что приводит к огромным размерам готовых библиотек, что вовсе не является пунктом в списке преимуществ для пользователей IPP.
Поэтому IPP собирается особым образом. Исходные файлы, включающие большое количество простых функций, перед компиляцией разрезаются специальным скриптом на много мелких, по одной функции на файл. И потом эти мини-файлы компилируются. Причем компилируются не один раз, а несколько — под разные архитектуры с соответствующими флагами. В результате получается несколько огромных статических библиотек — на каждый IPP домен. Но эти статические библиотеки склеены из очень небольших объектных файлов. Поэтому когда IPP линкуется статически к приложению, размер приложения увеличивается практически ровно на размер используемых из IPP функций, ни байтом больше.
Также в IPP имеется механизм генерации специализированных (custom) библиотек на базе существующих инструментов без необходимости открывать пользователям исходный код. А именно, из заголовочных файлов пользователь выбирает список интересующих его функций, после чего из огромных статических библиотек автоматически скриптом создается небольшая динамическая библиотека только с нужными функциями и их зависимостями. Более того, для дальнейшего сокращения размера эта динамическая библиотека может включать в себя варианты сборки указанных функций не под все варианты железа, а исключительно под заданный пользователем список платформ.
В ситуации, когда каждый дополнительный процент производительности библиотек IPP имеет значение, очень важным становится решение, на каком уровне осуществлять параллелизацию кода: внутри функций библиотеки, что хорошо для вызовов IPP из одного пользовательского потока, либо снаружи, на уровне пользовательских приложений, что хорошо для многопоточных приложений, самостоятельно разделяющих работу и данные для IPP.
Поскольку приложения бывают разные, и IPP сделаны тоже разные. А именно, в комплект поставки IPP входят по два набора библиотек в 32 и 64-битной версиях: одна чисто однопоточная внутри, а вторая — с внутренним распараллеливанием значительного количества функций при помощи OpenMP (точный список функций прилагается в сопроводительных документах). Кроме того, для библиотек обработки изображения есть и еще одна версия — «мнопоточный слой» (Threading Layer), представляющая собой надстройку над однопоточной IPP и использующая либо OpenMP либо Intel TBB для внешнего распараллеливания работы над изображениями, разделяемыми для этого на фрагменты (тайлы). Исходные коды IPP Threading Layer доступны в пакете IPP и нужны тем, кто хочет получить максимально возможный контроль над параллельной работой своего кода.
Почти с самого возникновения IPP разработчикам пришлось озаботиться проблемой того, что конвейеры обработки изображений и сигналов, состоящие из отдельных функций IPP, работают медленнее, чем хотелось бы. Объясняется это просто: при вызове IPP-функций происходит как правило загрузка-выгрузка из кеша или даже из памяти, а эта операция может оказаться заметно дороже собственно вычислений. Этот эффект особенно заметен при обработке больших данных — не тех, что называют big data, а например, изображений формата FullHD (не говоря уже о 4К).
Решение объединить несколько функций внутри IPP в одну в этом случае не подходит — тогда вместо примитивов-кирпичиков мы получим причудливые детали из игры «тетрис», вставить которые в пользовательские приложения будет проблематично, а разнообразие таких возможных объединений превысит все разумные пределы.
В результате была реализована C++ надстройка над IPP, которая строила графы конвейеров, нарезала картинки на кусочки, и потом запускала параллельный цикл, который в каждом потоке выполнял не одну операцию, а весь IPP конвейер на отдельном тайле. В конце, конечно результаты склеивались. Сначала был сделан прототип, он показал приличное ускорение. Потом была создана настройка под названием DMIP (deferred-mode image processing). Далее, в 2011 году на одном из первых заседаний комитета стандартизации OpenVX в Khronos, DMIP был упомянут и горячо поддержан комитетом с учетом популярности графов у разработчиков железа. Так стандарт OpenVX получился основанным на графовой технологии. Стандарт OpenVX по разным причинам не получил достаточной популярности, но зато сейчас графовую парадигму поддерживает и развивает технологию команда Intel Graph API. А так как Graph API входит в OpenCV, OpenVINO, Movidius SDK, то налицо прямое влияние технологий IPP на стандарты компьютерного зрения и современные API.
IPP — полезные ссылки
Еще раз приведем самые главные ссылки из этой статьи.
Intel IPP от первого лица
Предоставим слово людям, в разные годы сыгравшим важную роль в судьбе Intel Performance Primitives.
Владимир Дудник, руководитель команды Intel IPP в 2009–2011 годах
По-моему, у IPP по прежнему очень сильная концепция — предоставить индустрии легкий, достаточно низкоуровневый слой абстракции от различий разных аппаратных платформ. Несмотря на существенный прогресс в развитии компиляторов, по-прежнему нет возможности из описания на языке высокого уровня получить оптимальный по размеру и производительности машинный код для функций преобразования Фурье, фильтров разного рода и т.п. Это означает что у IPP по-прежнему есть ниша, где она нужна и действительно полезна для ускорения разработки кросс-платформенных высокопроизводительных программ.
Думается, есть потенциальная возможность присмотреться к потребностям разных фреймворков глубокого обучения, там много достаточно стандартных, относительно простых операций, которые могут быть ускорены SIMD инструкциями. Часть из них, как правило многомерные свертки, покрываются библиотекой MKL, но и для IPP возможность применения можно найти.
Вадим Писаревский, лидер проекта OpenCV, участник команды IPPCV в 2006–2008 годах
Если говорить про IPP в целом, то, конечно, скорость у библиотеки выдающаяся. Особенно флагманские функции типа FFT. Ядра — чистый изумруд! К счастью, у меня была возможность немного поизучать исходники IPP в свое время, и местами это был просто учебник, как надо писать эффективный код.
В свое время команду IPP очень сильно заинтересовала проблема автогенерации кода, в частности, на OCaml, и впечатлили успехи проекта Spiral, который сумел автоматически сгенерировать ядра FFT и родственных преобразований — на уровне или даже обходивших по скорости реализованные в IPP. Часть этих ядер потом была включена в IPP. А меня, в свою очередь, эта тема зацепила настолько, что мой текущий проект, 13–14 лет спустя, с этой темой связан.
Павел Бердников, руководитель команды IPP QA в 2011–2015 годах, руководитель команды IPP в 2017–2020 годах
Работу в IPP я начал в QA команде в Сарове в 2000 г. с написания тестов, позже создав единую билдовую систему для такого сложного проекта, автоматизированный процесс построения и тестирования.
А 17 лет спустя в Нижнем Новгороде стал руководителем всей команды IPP. Пришлось знакомиться с партнёрами внутри Intel и пользователями за его пределами. Изменить способы планирования и разработки кода от старых waterfall & development к современным agile & DevOps. Пересмотреть стратегии проекта и придумать новые. Так проект больше сосредоточился на криптографии и компрессии данных, появились интересные направления работы и новые области развития.
Реалистичные планы по развитию проекта — развивать что есть и смотреть в смежные области. Фантастические планы, которые были ранее в мечтах, разбились о понимание мировых трендов и нужд наших пользователей. Пришло осознание, что бесконечные ресурсы, которые всегда очень хочется получить чтобы сделать больше и глубже, не дадут ожидаемого результата. Наверное, если бы я получил полную свободу действий и ресурсы, я бы пошёл дальше в область исследований новых алгоритмов, в область университетов и работы с ними.
Валентин Кубарев, руководитель команды Image & Signal Processing проекта Intel IPP, 2020 год — настоящее время
Работу в IPP я начал в качестве SW инженера в 2011 году, когда проект только переехал из Сарова в Нижний Новгород. Меня всегда интересовала работа, связанная с математикой и оптимизацией. Знакомство с IPP я начал с функциональности изменения размера изображения, после чего долгое время отвечал за поддержку, разработку и оптимизацию геометрических преобразований, таких как Resize, WarpAffine, WarpPerspective и т. д. C 2017 года активно участвовал в задачах связанных с криптографией, и, в итоге, в 2018 мы смогли открыть код IPP Crypto и выложить проект на GitHub. С конца 2018 года работал в другом проекте, в 2020 году снова вернулся в IPP, но уже как руководитель Image & Signal Processing домена. Считаю, что в данный момент данная часть проекта недооценена, поэтому активно работаю с пользователями продукта IPP и нашими партнёрами внутри компании Intel, чтобы вывести проект на новый уровень.