Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Open MPI

Глава 15 из книги "Архитектура приложений с открытым исходным кодом", том 2.
Оригинал: Open MPI, глава из книги "The Architecture of Open Source Applications" том 2.
Автор: Jeffrey M. Squyres
Перевод: Н.Ромоданов

15.3. Усвоенные уроки

Неизбежно, что при наличии такой разношерстной группы основных разработчиков Open MPI, мы должны были каждый раз что-то изучать, и что, как группа, мы должны были многому научиться. Ниже перечислены лишь некоторые из этих уроков.

Производительность

Производительность при передачи сообщений и использование ресурсов являются королем и королевой высокопроизводительных вычислений. Open MPI был специально разработан таким образом, чтобы мог работать на самом переднем крае высокой производительности: невероятно низкие задержки при отправке коротких сообщений, чрезвычайно высокая скорость добавления коротких сообщений в поддерживаемые сети, быстрое достижение максимальной пропускной способности для больших сообщений и т.д. Абстракция является хорошим делом (по многим причинам), но она должна разрабатываться с осторожностью с тем, чтобы она не ухудшала производительность. Или, иначе говоря: тщательно выбирайте абстракции, которые сами понемногу ухудшают производительность стеков вызовов (в сравнении со стеками вызовов с использованием API).

Т.е. также должны нужно признать, что в некоторых случаях следует выбрасывать абстракцию, а не архитектурное решение. Показательный пример: в Open MPI есть фрагменты ассемблерного кода, закодированные вручную, для некоторых из наиболее критичных к производительности операций, например, блокировка совместно используемой памяти и атомарные операции.

Стоит отметить, что на рис.15.1 и 15.2 показаны два различных варианта архитектуры Open MPI. В них не представлены стеки вызовов времени выполнения или обращение к слою вызовов для разделов кода, где нужна высокая производительность.

Усвоенный урок:

Допускается (хотя и нежелательно) и, к сожалению, иногда необходимо иметь объемистый и сложный код для достижения высокой производительности (например, вышеупомянутый ассемблерный код). Тем не менее, всегда предпочтительнее потратить время, пытаясь выяснить, как создать хорошие абстракции с тем, чтобы по мере возможности дискретизировать и скрыть сложность. Несколько недель проектирования могут сэкономить сотни или тысячи часов у разработчиков, которые им потребуются на поддержку запутанного непонятного кода, похожего на спагетти.

Стоя на плечах гигантов

Мы в Open MPI активно пытались избежать заново изобретать код, который кто-то уже написал (если такой код был совместим с лицензией BSD, используемой в Open MPI). В частности, у нас нет никаких угрызений совести относительно непосредственного повторного использования или взаимодействия с чужим кодом.

Когда делается попытка решить очень сложные технические задачи, то не место придерживаться принципа «изобретено не здесь»; единственное, что имеет смысл, всякий раз, когда это возможно, повторно использовать внешний код. Такое повторное использование кода позволяет разработчикам сосредоточиться на проблемах, которые уникальны для проекта Open MPI; нет смысла повторно решать проблему, которая кем-то уже решена.

Хорошим примером такого повторного использования кода является пакет GNU Libtool Libltdl. Libltdl это небольшая библиотека, которая предоставляет переносимый интерфейс API для открытых объектов DSO и поиска в них символов. Libltdl поддерживается в самых различных операционных системах и средах, в том числе и в Microsoft Windows.

В Open MPI можно бы было реализовать эти функциональные возможности самостоятельно, но — зачем? Libltdl является прекрасным образцом программного обеспечения, которое активно поддерживается, совместимо с лицензией Open MPI и предоставляет именно те функциональные возможности, которые были необходимы. Учитывая все это, разработчики Open MPI не получат каких-либо реальных выгод, если заново напишут эти функции.

Усвоенный урок:

Если где-нибудь есть подходящий решение, то не стесняйтесь и воспользуйтесь им и не тратьте время, пытаясь его повторно повторить.

Оптимизация обычно выполняемых операций

Еще один направляющий архитектурный принцип состоит в том, чтобы оптимизировать наиболее часто выполняемые операции. Например, ударение делается на разделение многих операций на две части: на настройку и многократно выполняемое действие. Предполагается, что настройка может оказаться затратной (что означает: медленной). Так что сделаем ее один раз, и покончим с ней. Оптимизируем гораздо более распространенный случай: повторно выполняемую операцию.

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

Усвоенный урок:

Разбиваем обычные операций (по крайней мере) на две части: настройка и повторяющееся действие. Мало того, что код будет работать лучше, его, может быть, будет проще поддерживать в течение долгого времени, поскольку различные действия разделены.

Прочие уроки

Было усвоено слишком много других уроков с тем, чтобы их можно было бы здесь подробно описать; приведем еще несколько уроков, которые можно суммировать следующим образом:

  • Нам повезло опереться на более чем 15 летний опыт исследований в области высокопроизводительных систем и еще в течение более восьми лет создавать проекты, которые были (в основном) успешными. Приступая к новому проекту программного обеспечения, посмотрите в прошлое. Удостоверьтесь в том, что понимаете, что уже было сделано, почему это было сделано и каковы были сильные и слабые стороны сделанного.
  • Концепция компонентов, которая допускает несколько различных реализаций одной и той же функциональности, спасала нас много раз, причем как технически, так и политически. Плагины — это дело хорошее.
  • Кроме того, мы постоянно добавляли и удаляли фремворки по мере необходимости. Когда разработчики начинают спорить о «правильном» способе реализации новой возможности, то добавляется фреймворк, который экранирует компоненты, реализующие эту возможность. Или когда приходят новые идеи, из-за которых становятся ненужными устаревшие фреймворки, то не стесняйтесь и удаляйте такие обертки.

Заключение

Если бы нам пришлось перечислить три наиболее важных факта, с которыми мы познакомились в проекте Open MPI, я думаю, что это бы выглядело следующим образом:

  • Одно и то же значение не подходит для всех (пользователей). Плагин времени выполнения и сопутствующая ему система параметров MCA предоставляют пользователям возможность гибкой настройки, что необходимо в мире переносимого программного обеспечения. Сложные системы программного обеспечения не могут (каждый раз) волшебным образом адаптироваться к конкретной системе; предоставление средств управления пользовательского уровня позволяет человеку понять и перенастроить, если программа ведет себя субоптимально.
  • Различия хороши. Разногласия между разработчиками также хорошая вещь. Охват проблем ведет к статус-кво; самодовольству не место. Фраза смелого аспиранта: "Давай, проверим это ...» может привести к возникновению базы для абсолютно новой возможности или к существенному усовершенствованию изделия.
  • Хотя это выходит за рамки данной книги, но важное место занимают люди и сообщество. Важное место.

К началу статьи