`

СПЕЦІАЛЬНІ
ПАРТНЕРИ
ПРОЕКТУ

Чи використовує ваша компанія ChatGPT в роботі?

BEST CIO

Определение наиболее профессиональных ИТ-управленцев, лидеров и экспертов в своих отраслях

Человек года

Кто внес наибольший вклад в развитие украинского ИТ-рынка.

Продукт года

Награды «Продукт года» еженедельника «Компьютерное обозрение» за наиболее выдающиеся ИТ-товары

 

Научные вычисления: архитектуры, форматы, инструментарий. Часть 2

0 
 

Несмотря на упомянутое в предыдущей статье кажущееся несоответствие требованиям нашей "суровой действительности", наступило время предупредить читателя -- разговор у наc будет долгим. И даже если вы не занимаетесь тем, что попадает в не очень хорошо определенную категорию "научных вычислений", не стоит игнорировать на первый взгляд отдаленную от "реалий" тему. Все программные средства, о которых рассказывалось и будет рассказываться в этом цикле статей, -- в своем роде уникальны и допускают куда более прозаичное применение.
Форматы

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

Впрочем, для начала обратимся к короткой формулировке, определяющей (или задающей) так называемые requirements (требования) -- святая святых всех процессов проектирования. Высокоуровневые требования к форматам представления научных данных на удивление универсальны: способность к объединению в одном файле записей самых разных типов и структур, ориентация на большие объемы данных, гарантируемая форматом и поддерживающим его инструментарием мобильность, обеспечение быстрого ввода/вывода, эффективное хранение на различных носителях и, наконец, расширяемость формата. Как видно из этого перечня, ничего сугубо специфического в нем нет -- именно такой формат данных был бы идеален, например, для мобильного представления больших мультимедийных проектов (энциклопедий) или контента интерактивного телевидения.

Уточняющая формулировка requirements, на основании которой фактически создавались существующие наиболее популярные реализации форматов научных данных, ненамного сложнее. Она требует от формата свойства "самоописания" (self-describing, обязательное наличие встроенных в сам файл описаний метаданных), компактности, возможности последовательного доступа, простоты как самого формата, так и спецификаций на сопутствующий инструментарий, стабильности развития, гарантирующей 100%-ную совместимость по принципу "сверху вниз".

Одно из самых важных требований -- "самоописание". Файл с научными данными может включать в себя совершенно разные фрагменты: форматированный документ с описанием условий эксперимента, таблицу данных, видеоряд, фиксирующий наиболее интересные моменты натурного опыта, информацию о математических моделях и результатах моделирования, короче говоря, -- множество весьма "несопоставимых" как по размеру, так и по структуре записей. Главное -- все они отражают различные аспекты чего-то одного целого. Представить себе монолитную программную систему (этакую научную "суперпрограмму"), способную "сжевать" все это разнообразие, очень трудно, а реализовать, наверное, невозможно.

Очевидное решение -- "дробление" одного файла, содержащего "разнообразие", на множество "однообразных" файлов -- на деле оказывается далеко не таким удачным: возникают слишком серьезные проблемы с хранением, доступом и управлением.

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

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

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

Как видно из этого краткого обзора, "подводных камней" при выборе формата много и все-таки... если вести речь о серьезных научных приложениях и их применении в реальной академической среде, где свободный обмен данными -- один из ключевых факторов собственно функционирования науки, существуют два реальных претендента на такую важную роль -- Иерархический формат данных (ИФД, HDF -- Hierarchical Data Format) и Единая сетевая форма представления данных (ЕСФПД, netCDF -- Network Common Data Form). Называть эти разработки "конкурирующими" можно очень условно, несмотря на единство целей, поставленных их создателями. Сегодня поддержка и HDF, и netCDF -- де-факто обязательное свойство настоящего научного ПО. Оба формата в той или иной мере соответствуют всем перечисленным требованиям, очень стабильно и давно развиваются, прошли через десятки серьезных архитектурных изменений и тысячи "полировок" кода реализаций подсистем поддержки. О последних: для обоих форматов созданы детальнейшим образом документированные (высокое качество документации обыкновенно свойственно программам с "научным" происхождением) мобильные библиотеки с интерфейсами для разных языков программирования (обычно C/С++, Fortran и Java, ставших непризнанными стандартами в научном сообществе).

Основной тип данных, хранимый/передаваемый с помощью файлов HDF и netCDF, -- конечно же, многомерный массив. Его роль настолько важна, что в англоязычной литературе он часто именуется Scientific Dataset (научный набор данных). Формат HDF, кроме того, предусматривает выделенные типы для растровых изображений, цветовых палитр, текстовых аннотаций и, наконец, для универсальных табличных данных с бинарным содержимым (возможная трактовка которых зависит от атрибутов). В формате netCDF для описания Scientific Dataset используется специальный язык -- CDL (Единый язык описания представления данных), синтаксически максимально приближенный к описанию структур в языке C:

// Шаблон CDL-описания
netCDF Данные_Эксперимента_1
// размерности
dimensions: ...
// имена и атрибуты переменных
variables: ...
// собственно данные
data: ...

Более того, несмотря на простоту "ручного" формирования CDL-описаний, пакет netCDF предоставляет в распоряжение пользователя и программиста утилиты, не только автоматизирующие процесс создания CDL-"программы" по содержимому netCDF-файла и генерацию netCDF-файла из CDL-описания, но и формирующие программу на С или Fortran, "разбирающую" файл до уровня подпрограмм, возвращающих типизированные элементы упрятанной в него структуры.

Даже не пытаясь подвести итоги нашему краткому знакомству с основными, можно сказать -- обязательными хотя бы для знания о самом факте их существования, форматами представления научных данных, следует только отметить, что обе разработки очень просты в освоении хорошо подготовленным "непрограммирующим" или прикладным программистом. Интерфейсы библиотечных функций просты и "отточены" (это свойство трудно и назвать иначе, и объяснить -- оно становится понятным при детальном ознакомлении с конкретными программами), документация настолько подробна, что иногда кажется даже назойливой. Кроме того, библиотеки и сопутствующий инструментарий очень мобильны: они работают "на всем, что движется" и легально бесплатно доступны (в том числе и для коммерческих приложений) в исходных текстах на основании весьма нетребовательных лицензий.


Языки быстрого прототипирования

Эта категория программ является обязательной в обширном инструментальном наборе, ориентированном на "научные приложения". И, как обычно, никакой четкой определенности в самом термине "язык прототипирования" (ЯП) нет. Впрочем, само название подразумевает соответствие языка ряду некоторых очевидных требований. Во-первых, действительно удачный ЯП должен быть синтаксически максимально близким к используемому при разработке реального проекта языку программирования. Это уменьшает дистанцию между программой-прототипом и конечным продуктом и "облегчает жизнь" разработчикам, не требуя от них изучения чего-то принципиально нового. Во-вторых, ЯП буквально обязан быть интерпретируемым языком -- в противном случае для осуществления неизбежных процедур отладки в ходе разработки прототипа потребуются сложные инструментальные средства, которые как минимум кто-то должен создать, а сам разработчик -- освоить. В-третьих, интерпретатор языка должен быть быстрым -- прототип прототипом, но научные данные традиционно характеризуются большими размерами и необходимостью интенсивных вычислений. И наконец, в-четвертых,-- несмотря на синтаксическую близость к "чему-то популярному", семантика языка должна обеспечивать действительно быстрое и эффективное "модельное" программирование класса задач, специфического для данной прикладной области.

Подобный перечень весьма противоречивых требований "овеществить" очень непросто, и каждый новый удачный ЯП -- пусть маленькое, но все же событие в своем мире. К категории таких событий относится и объект нашего рассмотрения -- язык Nickle (название подчеркнуто шутливое, отражающее американскую присказку "my 5c" -- "мои 5 копеек", nickle -- пятицентовая монета), удостоенный доклада на конференции Usenix (Международная ассоциация передовых вычислительных систем). В нем автор Nickle так сформулировал поставленные им самим перед началом разработки языка требования: простота проекта и реализации, разделение концепций (ортогональность), позволяющая создавать и использовать языковые конструкции независимо друг от друга, ориентация на доказавшие успешность практическим применением языковые технологии.

Слишком много рассказывать о Nickle совершенно необязательно -- синтаксически язык очень похож на распространенный C, что обеспечивает короткий период освоения, семантически же он является гибридом усеченной версии Java и функциональных языков программирования. Характерные особенности семантики можно отобразить несколькими короткими примерами.

Как уже упоминалось ранее, массивы -- один из главных типов данных в научных вычислениях. Так как Nickle ориентирован на строго определенную прикладную область, работа с Scientific Dataset в нем максимально облегчена. Привычная синтаксическая конструкция "[]", ассоциирующаяся во многих языках программирования с операцией индексации массива, в Nickle играет несколько ролей, главная из которых -- неявно представленный конструктор. Так, строки вида "ИМЯ = [РАЗМЕР]СПИСОК_ИНИЦИАЛИЗАЦИИ" в Nickle означают создание Scientific Dataset с именем ИМЯ, заданной выражением РАЗМЕР размерностью, тип элементов которого определяется автоматически по данным из списка инициализации. Для явного указания типа элементов массива используется более близкая (и, по мнению многих пользователей Nickle и Java, более удачная) к синтаксису языка C форма: "ТИП_ЭЛЕМЕНТА[РАЗМЕРНОСТЬ] ИМЯ = СПИСОК_ИНИЦИАЛИЗАЦИИ". Итак, две следующие строки на Nickle создают два Scientific Dataset: первый -- один массив с динамической типизацией элементов, второй -- с предопределенной статической:

Dyn_SD = [2,2] 0,1,1,0 ;
real[2,2] Stat_SD = 0,1,1,0 ;

Сразу следует упомянуть об одной важной особенности Nickle -- типах данных. В отличие от большинства скриптовых языков с динамической типизацией (где переменные являются "контейнерами", в которые можно "уложить" значения любого типа), Nickle основан на гибридной модели -- при явном описании типа переменной в действие "включается" статическая типизация -- встроенные механизмы проверки допустимости всех последующих операций. Это исключительно полезное при разработке прототипов вычислительных программ свойство как раз и придает Nickle ту самую "изюминку", отличающую его от многих куда более известных разработок. Кроме того, основные встроенные типы -- целые (int) и действительные (real) числа -- в Nickle имеют так называемую "бесконечную точность" (infinite precision) и весьма интересные реализации представления как бесконечно повторяющихся последовательностей в числах, так и иррациональных чисел. Например, в результате выполнения операции 1/6 Nickle выдаст результат во вполне соответствующей принятой в математике форме записи: 0.16. Для представления иррациональных чисел в Nickle встроена специальная библиотека, реализующая вычисления с задаваемой пользователем точностью.

К менее обусловленным ориентацией на прикладную область свойствам языка можно отнести наличие встроенного "сборщика мусора" (garbage collector), полностью освобождающего программиста от забот с управлением памятью, поддержку механизмов обработки исключительных ситуаций и пространства имен (синтаксически похожие на аналогичные возможности C++) и собственную встроенную высокомобильную реализацию потоков (нитей, threads) с необходимыми операциями синхронизации. Для использования всех этих возможностей Nickle требует минимума усилий от программиста как при изучении, так и при написании "модельных" программ. Впрочем, здесь шаблонный пример говорит сам за себя:

import Semaphore ;
semaphore S_1, S_2 ;
void function child_thread()
...
wait(S_1) ;
...
signal(S_2) ;
...


void function parent_thread()
...
S_1 = new(1) ;
S_2 = new(0) ;
...
thread t1 = fork child_thread() ;
...
wait(S_2) ;
...
signal(S_1) ;
...
Thread::join(t1) ;
...

В нем использованы и пространства имен (в частности, "подключение" в область видимости программы пространства имен Semaphore командой import) и запуск нового потока командой fork, получение результата выполнения потока с помощью вызова Thread::join(), а также механизмы синхронизации между потоками, основанные на применении семафоров. Все эти возможности "уложились" в минимум ключевых слов и вызовов функций.

Подобные неожиданные для "маленького языка" свойства (которые в недопустимых для небольшой статьи нюансах куда более интересны) позволяют прототипировать с помощью Nickle как программы для параллельных вычислений (например, для модных дешевых кластеров типа Beowulf), так и основанные на использовании программных шин распределенные комплексы программ, концентрируясь исключительно на проверке сутевой части будущих программ -- правильности вычислительных алгоритмов.

Обзор Nickle был бы не полным без указания двух главных особенностей -- компактности и мобильности реализации. Дистрибутив, распространяемый в исходных текстах, "умещается" в файле размером всего... 400 KB, при этом разработчик Nickle умудрился использовать исключительно вызовы функций, соответствующие стандарту POSIX, благодаря чему Nickle прекрасно "чувствует себя" фактически на любой современной платформе.


Языки междисциплинарного моделирования

Собственно, в заглавии этого небольшого раздела статьи множественное число не совсем уместно, ведь на самом деле существует фактически один-единственный язык, попадающий в этот класс. Называется он Modellica и предназначен для упрощения построения и изучения моделей физических систем, объединяющих элементы (подсистемы) различной природы. Задачи моделирования -- традиционная и исключительно важная область "научных приложений" хотя бы потому, что находится "на грани" между "чистой наукой" и инженерией. Здесь, естественно, "правят бал" уравнения -- дифференциальные, алгебраические и моделирующие поведение дискретных систем. Составление системы уравнений, выбор подходящего решающего их алгоритма и получение достоверного решения -- задачи далеко не из простых, каждая из них является самостоятельной научной дисциплиной. Создатели же Modellica пытались формализовать накопленные знания, частично автоматизировать и максимально упростить решения всех этих задач без утраты достоверности результатов. Следует отметить, что популярность Modellica как идеи и поддерживающего инструментального набора исключительно высока -- существует международная ассоциация "пользователей" Modellica, в которую входят и ведущие компании--разработчики моделирующего научно-инженерного ПО.

По сути, Modellica представляет собой специализированный объектно-ориентированный язык программирования, оперирующий весьма "вещественными" объектами. В терминах этого языка моделируемая система представляется соединением компонентов-моделей. Например, если идет речь о системе, содержащей соединенные валом двигатель и коробку передач, ее Modellica-описание будет выглядеть весьма прозрачно:

model Система
Motor Двигатель ;
Gearbox Коробка_Передач ;
equations
connect(Коробка_Передач.Вал_Вх,
Двигатель.Вал_Вых);
end

Первая часть описания (до ключевого слова equations) специфицирует используемые в системе компоненты, вторая -- ее топологию. Выражения в первой части, например, "Motor Двигатель ;", как и положено в языках программирования, можно "озвучить" приблизительно так: "компонент системы с именем Двигатель типа Motor" (или "по-программистски" -- создать объект Двигатель класса Motor). Описание топологии "connect(Коробка_Передач.Вал_Вх, Двигатель.Вал_Вых);", соответственно, на "человеческом языке" будет звучать так: "соединить (connect) вал Вал_Вых двигателя с валом Вал_Вх коробки передач".

За подобными высокоуровневыми моделями скрываются предопределенные создателями Modellica "подмодели" очень большого количества классов реальных физических объектов, две из которых (Motor и Gearbox) были использованы в нашей "программе". Общий синтаксис их описания остается прежним, но в нем добавляется буквально несколько новых ключевых слов языка, самым главным из которых является connector -- описание "интерфейса" реального объекта. В нашем примере такими интерфейсами были "Вал_Вх" и "Вал_Вых". Connector характеризуется перечнем измеримых физических величин, необходимым для описания взаимодействия. Например, с принятой нами в примере степенью детализации connector типа Вал может характеризоваться только крутящим моментом и частотой вращения. Для поддержки моделирования объектов разной природы в Modellica встроены более 450 описаний физических величин, именуемых базовыми типами данных. Все остальные уже упомянутые элементы (Вал_Вх, Вал_Вых, Motor, Gearbox) являются объектами сложных типов данных -- классов. Естественно, что, кроме множества предопределенных в базовых библиотеках классов, существует возможность создавать и принципиально новые модели с полноценным использованием всех достоинств объектно-ориентированного проектирования.

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

Ready, set, buy! Посібник для початківців - як придбати Copilot для Microsoft 365

0 
 

Напечатать Отправить другу

Читайте также

 

Ukraine

 

  •  Home  •  Ринок  •  IТ-директор  •  CloudComputing  •  Hard  •  Soft  •  Мережі  •  Безпека  •  Наука  •  IoT