Новости: Разработка оптимизирующих компиляторов для современных суперкомпьютеров

Разработка оптимизирующих компиляторов для современных суперкомпьютеров

23 ноября 2001

Недавно вышла книга Кена Кеннеди (Ken Kennedy) и Рэнди Аллена (Randy Allen) , основанная на разработках последних двадцати лет в области оптимизирующих компиляторов.

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

Языки и библиотеки эволюционировали от простейших библиотек BLAS (Basic Linear Algebra Subroutines) до крупных программных комплексов, ориентированных на суперкомпьютеры. Помимо этого, параллельные языки и стандартные интерфейсы обмена информацией, такие, как MPI, позволили создавать переносимые программы. Примерно такой же прогресс произошёл в теории оптимизации программ и на практике. Без соответствующих языков программирования и компиляторов ресурсы суперкомпьютеров использовались бы неэффективно.

Критическим вопросом является развитие языков, позволяющих представить программу на достаточно высоком и легко понятном программисту уровне, но одновременно обеспечивающих достаточный уровень детализации, необходимый компиляторам для эффективного использования параллелизма. Компилятор является "мостом" между программистом и архитектурой компьютера. Знание того, что может или не может компилятор, является критическим. Каждый компилятор должен максимально использовать возможности конкретной архитектуры. Какой бы ни был уровень параллельности программы, именно компилятор, в конечном счёте, определит эффективную производительность.

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

Большие успехи были достигнуты в преобразованиях, основанных на анализе графов зависимостей. 20 лет назад теория зависимостей считалась применимой главным образом к векторным машинам, так как она могла выявлять полностью векторизуюмые операции и осуществлять преобразования вроде перестановки циклов, которые могли бы повысить векторный потенциал программы. Тем не менее, не рассматривалась возможность её широкого применения помимо векторизации. Сегодня теория зависимостей признана не только основополагающей для раскрытия неявного параллелизма (на уровне инструкций VLIW, суперскалярного, векторного или многопроцессорного) в последовательных языках, но также крайне важной для адаптирования кода, сгенерированного из языков высокого уровня, к индивидуальным особенностям реальных архитектур. Например, анализ зависимостей стал базовым инструментом для реструктуризации программ с целью повысить эффективность задействования иерархической памяти за счёт многократного использования регистров и кэш-памяти. Проектирование компьютеров стало процессом, ориентированным на языки программирования и требующим наличия соответствующей технологии компиляции.

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

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

Смотрите также:


© Лаборатория Параллельных Информационных Технологий, НИВЦ МГУ Rambler's Top100