phihist-essay/main.typ

250 lines
No EOL
23 KiB
Typst
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#let text-indentation = 1.25cm
#let text-size = 14pt
#let leading = 1em
#set text(
font: "Times New Roman",
size: text-size,
lang: "ru"
)
#show heading: set text(size: text-size)
#set page(
paper: "a4",
margin: (
top: 2cm,
bottom: 2cm,
left: 3cm,
right: 1cm
),
numbering: "1"
)
#set heading(
numbering: "1.1.1.1",
)
#show heading.where(level: 1): set block(below: leading*2)
#show heading.where(level: 2): set block(above: leading*2, below: leading*2)
#show heading.where(level: 3): set block(above: leading*2, below: leading*2)
#show heading: it => pad(left: text-indentation, it)
#show figure: it => pad(top: leading, bottom: leading, it)
#set par(
justify: true,
leading: leading,
first-line-indent: (
amount: text-indentation,
all: true
),
)
#show "〜": h(text-indentation)
#align(
center,
outline(
title: "СОДЕРЖАНИЕ"
)
)
#pagebreak()
#align(
center,
pad(
left: -text-indentation,
heading(
numbering: none,
"Введение"
)
)
)
*Актуальность темы*: развитие технологий тесно связано с ростом объёмов обрабатываемых данных, особенно в сфере искусственного интеллекта. В связи с этим история высокопроизводительных вычислений становится как никогда актуальной. Рост массивов данных, развитие ИИ и необходимость ускорения вычислений делают историю языков и моделей программирования для HPC особенно важной. Эволюция подходов позволяет оптимизировать параллельные вычисления на суперкомпьютерах и ускорителях вроде GPU. Ограничения аппаратного обеспечения и растая сложность задач, требующих распределённой обработки, ведут к появлению новых вычислительных моделей.
Первым высокоуровневым языком для HPC стал Fortran, разработанный IBM в 1954 году под руководством Джона Бэкуса, который обеспечил эффективность на быстро эволюционирующем оборудовании и остаётся стандартом для бенчмарков TOP500@noauthor_frequently_nodate. В 19601970-х годах последовательное программирование уступило место параллельным подходам из-за роста многоядерных систем@noauthor_history_nodate.
В контексте развития высокопроизводительных вычислений особую роль сыграли параллельные модели и языки программирования. Уже в 1990-е годы сформировались ключевые подходы -- *message passing* и *shared memory*@noauthor_mpi_nodate. Стандарт MPI (1994 @noauthor_mpi_nodate) стал основой для распределённых систем и фактически закрепился как де-факто стандарт параллельных вычислений на кластерах. Параллельно развивался OpenMP (1997 -- для Fortran и 1998 -- для C/C++), ориентированный на многопоточное программирование для многоядерных CPU.
Следующий значимый этап связан с появлением GPU-программирования. В 2007 году NVIDIA представила CUDA@noauthor_cuda_nodate, впервые предложив удобную модель для унифицированных вычислений на GPU. Её развитие было дополнено открытым стандартом OpenCL@noauthor_opencl_nodate (2008), получившим поддержку NVIDIA и AMD. Параллельно появился Chapel -- язык, создававшийся Cray в рамках программы DARPA HPCS (20022012) и ориентированный на высокопроизводительную параллельность в масштабах суперкомпьютеров@balaji_chapel_2015. Эти модели существенно расширили возможности обработки данных, обеспечив переносимость и адаптивность к гетерогенным вычислительным системам.
В итоге эволюция -- от классических решений вроде Fortran до современных GPU-ориентированных моделей CUDA и OpenCL -- значительно упростила разработку высокопроизводительных алгоритмов. Смещение парадигм в сторону *параллелизма данных* и *гетерогенных вычислений* определяет современное состояние HPC и формирует требования к моделям программирования будущего.
#pagebreak()
= Ранние языки для научных расчётов
== Fortran -- первый язык для научных вычислений
Fortran (аббревиатура от *FOR*-mula *TRAN*-slation, "транслятор формул") разработан командой IBM под руководством Джона Бэкуса в 19541957 годах. Первая версия (Fortran I) выпущена в 1957 для компьютера IBM 704@noauthor_fortran_nodate. Проект начался из-за того, что написание программ в машинных кодах было крайне трудоёмким, как характеризовал этот процесс сам Бэкус: "Рукопашный бой с машиной@noauthor_fortran_nodate."
Ключевой проблемой был разрыв между мышлением учёных и инженеров -- формулами -- и тем, что понимала машина -- машинные коды. Fortran был сделан так, что код на этом языке был довольно близок к математической нотации (@listing-1).
#figure(
```f90
Y = A*X**2 + B*X + C
```,
caption: [Пример кода на языке Fortran]
) <listing-1>
Такой подход позволил уменьшить как объёмы кода, так и снизить количество ошибок при его написании.
Компиляторы Fortran принесли новые виды оптимизации кода: развёртку циклов, распределение регистров, оптимизация повторяющихся подвыражений и другие. Что особенно важно -- генерируемый код был сопоставим по эффективности с ассемблерным кодом, написанным вручную, а иногда даже быстрее.
Таким образом, Fortran стал фундаментом для высокопроизводительных вычислений:
#list(
[
стандартизация научных расчётов: общий язык для численного программирования;
],
[
библиотеки: BLAS, LINPACK/LAPACK и другие фундаментальные библиотеки написаны на Fortran;
],
[
портируемость: код можно было переносить между разными компьютерами, для которых был доступен компилятор Fortran;
],
[
долголетие: современные версии до сих пор используются в суперкомпьютерных центрах.
],
marker: "-",
indent: text-indentation,
)
При этом разработка и улучшение Fortran не остановилась, отдельные его модули и библиотеки до сих пор используются для высокопроизводительных вычислений, а последняя версия языка была выпущена в 2023 году.
== Алгол, Лисп и компиляторы
Но не Фортраном единым замыкается разработка программ.
=== Algol
В 1958 году комитетом европейских и американских учёных на съезде в институте ETH в Цюрихе был разработан язык программирования ALGOL (аббревиатура от *ALGO*-rithmic *L*-anguage, "алгоритмический язык"), точнее его вариант ALGOL 58 @noauthor_why_nodate.
В ходе разработки языка были выведены его ключевые концепции:
#list(
[ блочная структура программ; ],
[ разрешение рекурсии; ],
[ формальное описание синтаксиса в форме BNF-нотации. ],
marker: "-",
indent: text-indentation,
)
Многи последующие императивные языки программирования позаимствовали синтаксис Алгола -- но стоит отметить, что сам язык широкого распространения за пределами научных вычислений не получил.
=== Lisp
В 1985 году Джон Маккарти представил миру Lisp (аббревиатура от *Lis*-t *P*-rocessing) -- язык программирования для символьных вычислений и ИИ @wexelblat_history_1978.
Особенностями языка можно назвать:
#list(
[ "функции первого класса" -- их можно передавать, возвращать и проводить композицию; ],
[ каррирование -- преобразование функции множества аргументов в набор вложенных функций; ],
[ отсутсвие циклов -- их заменили рекурсией; ],
[ универсальная структура данных -- список; ],
[ символьное дифференцирование; ],
marker: "-",
indent: text-indentation,
)
Lisp позже повлияли на Python (list comprehensions), JavaScript (функции высшего порядка), языки типа Haskell, Scala и другие.
Также этот язык является прародителем функционального программирования, хотя он и является мультипарадигменным.
=== Оптимизирующая компиляция
Как уже было сказано ранее, компилторы стали применять систематические оптимизации.
Ключевые достижения:
#list(
[ компилятор Fortran мог генерировать более эффективный ассемблерный код, по сравнению с человеком; ],
[ анализ потока данных @hecht_flow_1977; ],
[ алгоритмы оптимизации графов (например, "алгоритм Хайтина" для раскраски графов и последующего распределения регистров); ],
marker: "-",
indent: text-indentation,
)
Для HPC оптимизирующие компиляторы стали критическим звеном между абстрактным кодом и эффективным использованием железа. Современные компиляторы (GCC, LLVM, Intel ICC) применяют сотни проходов оптимизации: векторизацию, предсказание переходов, межпроцедурную оптимизацию, полиэдрическую оптимизацию для вложенных циклов, однако база была заложена давно.
#pagebreak()
= Векторные- и суперкомпьютеры
== Концепция векторных вычислений
Векторные вычисления представляют собой фундаментальную ступень развития высокопроизводительных вычислительных систем, которая позволила достичь качественного скачка в производительности при решении задач, требующих обработки больших однородных массивов данных.
=== Суперкомпьютеры Cray и становление векторной обработки
Компания Cray Research, основанная Сеймуром Креем в 1972 году, стала пионером в области векторных суперкомпьютеров. Первая машина серии Cray-1, представленная в 1976 году, продемонстрировала революционный подход к организации вычислений@noauthor__nodate. Архитектура системы была построена на принципе конвейерной обработки векторных данных, что позволяло выполнять одну операцию над множеством элементов данных одновременно. Главная память машины состояла из 16 независимых блоков по 64 тысячи машинных слов каждый, а 12 функциональных модулей позволяли выполнять логические, скалярные и векторные операции над этими данными с высокой степенью параллелизма.
Ключевое преимущество векторной архитектуры заключалось в том, что одна векторная инструкция заменяла целый цикл скалярных операций. Это сокращало количество необходимых к исполнению команд и устраняло накладные расходы на управление циклами. Для научных и инженерных расчетов, где типичными являются операции с матрицами и массивами данных, такой подход обеспечивал многократное ускорение по сравнению со скалярными процессорами того времени.
=== Модель SIMD как основа векторизации
Концептуальной основой векторных вычислений стала модель SIMD, сформулированная в таксономии Флинна@flynn_very_1966. В своей ранней реализации эта модель предполагала, что один поток команд управляет обработкой множества потоков данных параллельно. Векторный процессор фактически реализовывал данную парадигму аппаратно: единственная векторная инструкция запускала идентичную операцию над всеми элементами векторного регистра.
Важно отметить, что ранняя форма SIMD в векторных суперкомпьютерах и современные векторные расширения процессоров существенно отличаются. Векторные машины работали с векторами переменной длины и обладали специализированными конвейерами для различных типов операций, а SIMD-расширения современных процессоров оперируют фиксированными по размеру векторами для исполнения этих операций ничего кроме самого процессора не требуется.
=== Векторные расширения в языке Fortran
Параллельно с развитием аппаратных векторных систем происходила эволюция программных средств, позволяющих эффективно использовать возможности векторной обработки@chang_support_2004. Язык Fortran в стандарте Fortran 90 получил расширение в виде конструкции для работы с массивами как с едиными объектами, что позволяло программистам того времени выражать векторные операции в знакомой математической нотации.
Компиляторы Fortran получили возможность автоматической векторизации циклов, распознавая паттерны кода, которые могли быть преобразованы в векторные инструкции@allen_automatic_1987. Это означало, что существующий код мог быть оптимизирован для векторных архитектур без полного переписывания, хотя наибольшая эффективность достигалась при использовании явных векторных конструкций языка. Появление директив компилятора также позволило программистам явно управлять процессом векторизации, указывая компилятору на возможности параллелизма в коде.
Развитие векторных вычислений заложило основу для современных параллельных архитектур и продолжает оставаться актуальным в контексте современных процессоров с SIMD-расширениями и графических ускорителей, использующих сходные принципы обработки данных.
== Новые компиляторные оптимизации
Параллельно с развитием векторных архитектур происходила модернизация в технологиях компиляции, направленная на максимальное использование возможностей современного оборудования. Компиляторы превращались из простых трансляторов высокоуровневого кода в машинный в сложные системы оптимизации, способные радикально трансформировать программу для достижения максимальной производительности.
Центральной задачей стала векторизация циклов. Компиляторы научились анализировать структуру циклов и определять, можно ли безопасно преобразовать последовательные итерации в единую векторную операцию. Для успешной векторизации цикла компилятору необходимо доказать, что между итерациями отсутствуют зависимости, так как в обратном случае применение векторных оперций приведёт к некорректным результатам вычисления.
Неполное разворачивание циклов стало одной из ключевых техник оптимизации -- компилятор мог группировать несколько итераций цикла, что давало ему возможность переупорядочить инструкции и уже затем, возможно, заменить их векторными операциями. Цикл всё ещё присутствует, но он может быть значительно меньше оригинального варианта.
Компиляторы, такие как для TI ASC и Cray Fortran, анализировали циклы на отсутствие зависимостей данных между итерациями, чтобы преобразовать последовательный код в векторные операции@morgan_compiling_2018. Это обеспечивало безопасность параллелизма без изменения результатов программы. Методы включали решение систем диофантовых уравнений для доказательства независимости.
Программисты использовали директивы (например, Cray VECTOR directives@noauthor_vectorization_nodate) для подсказок компилятору о безопасной векторизации при неполном статическом анализе. Межпроцедурный анализ учитывал вызовы функций для глобальной векторизации, как в Convex Application Compiler. Эти нововведения легли в основу современных компиляторов.
#pagebreak()
#align(
center,
pad(
left: -text-indentation,
heading(
numbering: none,
"СПИСОК СОКРАЩЕНИЙ"
)
)
)
ИИ -- искуственный интеллект
HPC (High-Performance Computing) -- высокопроизводительные вычисления
GPU (Graphics Processing Unit) -- графический процессор
SIMD (Single Instruction, Multiple Data) -- вычислительный подход, когда одна инструкция исполняется над некоторым массивом данных в один проход
#pagebreak()
#align(
center,
pad(
left: -text-indentation,
heading(
numbering: none,
"СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ"
)
)
)
#bibliography(
"references.bib",
title: none,
style: "gost-r-7-0-5-2008-numeric-alphabetical.csl"
)