Какие функции нужны пользователям от интерфейса MPI C ++?


28

Версия стандарта MPI 3.0 формально удалила интерфейс C ++ (ранее он был устаревшим). Хотя реализации все еще могут поддерживать его, новые функции в MPI-3 не имеют интерфейса C ++, определенного в стандарте MPI. См. Http://blogs.cisco.com/performance/the-mpi-c-bindings-what-happened-and-why/ для получения дополнительной информации.

Мотивация для удаления интерфейса C ++ из MPI заключалась в том, что он не имел существенного значения по сравнению с интерфейсом C. Было очень мало различий, кроме «s / _ / :: / g», и многие функции, к которым привыкли пользователи C ++, не использовались (например, автоматическое определение типа с помощью шаблонов).

Как человек, который участвует в форуме MPI и работает с рядом проектов C ++, в которых реализован собственный интерфейс C ++ для функций MPI C, я хотел бы знать, каковы желательные особенности интерфейса C ++ для MPI. Несмотря на то, что я ни к чему не привержен, мне было бы интересно увидеть реализацию автономного интерфейса MPI C ++, который отвечает потребностям многих пользователей.

И да, я знаком с Boost :: MPI ( http://www.boost.org/doc/libs/1_54_0/doc/html/mpi.html ), но он поддерживает только функции MPI-1, и модель сериализации будет крайне сложно поддерживать RMA.

Один интерфейс C ++ к MPI, который мне нравится, это Elemental ( https://github.com/poulson/Elemental/blob/master/src/core/imports/mpi.cpp ), так что, возможно, люди могут предоставить некоторые за и против, что подходить. В частности, я думаю, что MpiMap решает существенную проблему.


Я не думаю, что это подходящее место для такого вопроса.
Джек Полсон

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

Этот вопрос является ценным, и я думаю, что он мог бы получить некоторые ценные ответы в более широких списках рассылки по вычислительной науке, если бы он находился там. (Может быть, NA-digest, SIAM-CSE или даже публичная публикация на G +?) Этот вопрос может не подходить для сайта Stack Exchange, поскольку он субъективен (см. Scicomp.stackexchange.com/help/dont-ask ). , Пока ответы конкретны и сосредоточены на конкретных случаях использования (без существенных повторов или совпадений), я думаю, что это стоит оставить открытым.
Джефф Оксберри

@Jeff: Вопрос очень похож на опрос для меня. Я не оспариваю, что это ценно, но я не вижу единого принятого ответа. Будет ли такой вопрос необычным для форума MPI?
Джек Полсон

@JackPoulson Я не хочу знать, что разработчики считают правильным ответом; Я хочу знать, что нужно ученым в области вычислительной техники. В этом отношении на вопрос есть объективные ответы. Нет правильного ответа, но это не значит, что это субъективная ситуация.
Джефф

Ответы:


17

Позвольте мне сначала ответить, почему я думаю, что интерфейсы C ++ к MPI, как правило, не были слишком успешными, долго думая об этой проблеме, пытаясь решить, следует ли нам просто использовать стандартные привязки C MPI или строить что-то на более высоком уровне. :

Когда вы смотрите на реальные коды MPI (скажем, PETSc, или в моем случае. II), можно обнаружить, что, возможно, удивительно, что количество вызовов MPI на самом деле не очень велико. Например, в 500 000 строк сделки. II, всего около 100 вызовов MPI. Следствием этого является то, что боль, связанная с использованием низкоуровневых интерфейсов, таких как привязки MPI C, не слишком велика. И наоборот, нельзя было бы получить все это с помощью интерфейсов более высокого уровня.

Мое второе замечание заключается в том, что во многих системах установлено несколько библиотек MPI (разные реализации MPI или разные версии). Это создает значительную трудность, если вы хотите использовать, скажем, boost :: mpi, который не просто состоит из заголовочных файлов: либо необходимо несколько установок этого пакета, либо нужно собрать его как часть проект, который использует boost :: mpi (но это опять проблема сама по себе, учитывая, что boost использует собственную систему сборки, которая не похожа ни на что другое).

Так что я думаю, что все это совпало с текущим набором интерфейсов C ++ к MPI: старые привязки MPI C ++ не давали никаких преимуществ, а внешние пакеты испытывали трудности с реальным миром.

Это все, что я думаю, вот что я хотел бы получить от убойного интерфейса, который я хотел бы получить от интерфейса более высокого уровня:

  • Это должно быть универсальным. Необходимость указания типа данных для переменной явно не похожа на C ++. Конечно, это также приводит к ошибкам. Класс MpiMap от Elemental уже был бы хорошим первым шагом (хотя я не могу понять, почему, черт возьми, MpiMap::typeпеременная не является статической константой, так что к ней можно получить доступ без создания объекта).

  • Он должен иметь возможности для потоковой передачи произвольных типов данных.

  • Операции, которые требуют MPI_Opаргумента (например, сокращения), должны хорошо интегрироваться с std::functionинтерфейсом C ++ , так что легко просто передать указатель на функцию (или лямбду!) Вместо того, чтобы неуклюже регистрировать что-то.

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


Одна из проблем, связанных с сериализацией в Boost :: MPI, заключается в том, что она не работает с односторонними (иначе говоря, RMA). Считаете ли вы, что можно будет создать типы данных MPI для объектов C ++, которые интересуют пользователей? Конечно, в теории все должно поддерживаться, но я предпочитаю начинать с более прагматичной цели.
Джефф

Я думаю, что ошибочно думать, что сериализованный тип данных может когда-либо работать с односторонней связью. Это предполагает, что сериализация включает в себя только упаковку данных в строку, а с другой стороны, распаковку их снова. Но функции сериализации могут делать гораздо больше (например, отслеживать указатели на другие объекты, считать байты, которые были сериализованы и т. Д.), Чем можно ожидать, если вы ничего не можете выполнить на хосте назначения. Я считаю, что сериализация в стиле C ++ и одностороннее общение - это просто начало. Я думаю, что никто не должен ожидать, что это сработает, поэтому мало что будет упущено.
Вольфганг Бангерт

Привет, Вольфганг, ты прав, что MpiMap был бы более элегантным, если бы он использовал статическую переменную-член const. Я реорганизовал реализацию: github.com/poulson/Elemental/commit/…
Джек Полсон,

Да, намного приятнее :-)
Вольфганг Бангерт

+1 о не так много MPI звонков @WolfgangBangerth. По сути, mpi должен делать вычисления быстрее, вы хотите минимизировать вызовы mpi, потому что они стоят вам!
Чарльз

6

Чтобы начать движение, вот две мои потребности:

  • Интерфейс должен быть в состоянии устранить избыточные или ненужные аргументы, например, MPI_IN_PLACE.
  • Интерфейс должен автоматически обнаруживать встроенные типы данных аля Elemental's MpiMap.
  • Если / когда это возможно, определяемые пользователем типы данных должны создаваться для классов.

5

Мой список в произвольном порядке предпочтений. Интерфейс должен:

  • быть только заголовком, без каких-либо зависимостей, но <mpi.h>и стандартной библиотеки,
  • быть универсальным и расширяемым,
  • быть неблокирующим только (если вы хотите заблокировать, то блокируйте явно, не по умолчанию),
  • разрешить основанную на продолжении цепочку неблокирующих операций,
  • поддерживать расширяемую и эффективную сериализацию (например, Boost.Fusion, которая работает с RMA),
  • иметь нулевой штраф за абстракцию (т. е. быть по крайней мере так же быстро, как интерфейс C),
  • быть в безопасности (деструктор неготового будущего называется? -> std :: terminate!),
  • иметь сильный DEBUGрежим с тоннами утверждений,
  • чрезвычайно безопасный для типов (больше никаких ints / void * для всего, черт возьми, я хочу, чтобы теги были типами!),
  • он должен работать с лямбдами (например, все уменьшить + лямбда),
  • последовательно использовать исключения в качестве механизма сообщения об ошибках и обработки ошибок (больше нет кодов ошибок! больше нет аргументов вывода функции!),
  • MPI-IO должен предлагать неблокирующий интерфейс ввода-вывода в стиле Boost.AFIO,
  • и просто следуйте хорошим современным практикам проектирования интерфейса C ++ (определяйте обычные типы, функции, не являющиеся членами, не являющимися друзьями, хорошо работайте с семантикой перемещения, операциями с диапазоном поддержки, ...)

Дополнительно:

  • Позвольте мне выбрать исполнителя среды MPI, то есть, какой пул потоков он использует. Прямо сейчас у вас могут быть приложения с сочетанием OpenMP, MPI, CUDA и TBB ... все в одно и то же время, когда каждая среда выполнения думает, что она владеет средой, и, таким образом, запрашивает у операционной системы потоки каждый раз, когда им хочется Это. Шутки в сторону?

  • используйте соглашение об именах STL (и Boost). Зачем? Каждый программист C ++ знает это.

Я хочу написать код так:

auto buffer = some_t{no_ranks};
auto future = gather(comm, root(comm), my_offsets, buffer)
              .then([&](){
                /* when the gather is finished, this lambda will 
                   execute at the root node, and perform an expensive operation
                   there asynchronously (compute data required for load 
                   redistribution) whose result is broadcasted to the rest 
                   of the communicator */
                return broadcast(comm, root(comm), buffer);
              }).then([&]() {
                /* when broadcast is finished, this lambda executes 
                   on all processes in the communicator, performing an expensive
                   operation asynchronously (redistribute the load, 
                   maybe using non-blocking point-to-point communication) */
                 return do_something_with(buffer);
              }).then([&](auto result) {
                 /* finally perform a reduction on the result to check
                    everything went fine */
                 return all_reduce(comm, root(comm), result, 
                                  [](auto acc, auto v) { return acc && v; }); 
              }).then([&](auto result) {
                  /* check the result at every process */
                  if (result) { return; /* we are done */ }
                  else {
                    root_only([](){ write_some_error_log(); });
                    throw some_exception;
                  }
              });

/* Here nothing has happened yet! */

/* ... lots and lots of unrelated code that can execute concurrently 
   and overlaps with communication ... */

/* When we now call future.get() we will block 
   on the whole chain (which might have finished by then!).
*/

future.get();

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


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

Что касается потоков и среды выполнения, MPI внутренне не использует ни потоков, ни потоков ОС (POSIX, Windows или Solaris, в зависимости от ОС). Я не совсем уверен, что понимаю требование здесь.
Джефф

Проблема в том, что MPI может произвольно запрашивать потоки из операционной системы. Мое приложение имеет пул потоков, и я хотел бы, чтобы MPI запрашивал эти потоки из моего пула потоков. В настоящее время это невозможно (и, как правило, это не проблема), если только у вас нет приложения, использующего OpenMP, TBB и MPI, каждое из которых имеет свои собственные пулы потоков, каждое из которых имеет 4-кратное количество ядер.
gnzlbg

1
MPI может, но обычно не использует потоки ОС внутри. В каждом знакомом мне случае (MPICH (2), MVAPICH2, OpenMPI, CrayMPI) только опция времени выполнения, предоставляемая пользователем, вызывает это, то есть по умолчанию это не так. Blue Gene / Q MPI является исключением, но в такой форме, которая не имеет отношения к этому обсуждению.
Джефф

Спасибо @Джефф! Не могли бы вы рассказать, как MPI обрабатывает несколько неблокирующих вызовов при использовании одного потока? Использует ли он сопрограммы / зеленые нити / волокна?
gnzlbg

2

Лично я не против вызывать длинные функции в стиле C по той причине, о которой говорил Вольфганг; на самом деле есть несколько мест, где вам нужно их вызвать, и даже тогда они почти всегда оборачиваются каким-то кодом более высокого уровня.

Единственное, что действительно беспокоит меня в MPI в стиле C, это пользовательские типы данных и, в меньшей степени, пользовательские операции (потому что я использую их реже). Что касается пользовательских типов данных, я бы сказал, что хороший интерфейс C ++ должен поддерживать общий и эффективный способ обработки этого, скорее всего, через сериализацию. Это, конечно, пройденный маршрут boost.mpi, который, если вы будете осторожны , поможет вам сэкономить много времени.

Что касается boost.mpiналичия дополнительных зависимостей (в частности, boost.serializationкоторые сами по себе не только для заголовков), я недавно натолкнулся на библиотеку сериализации C ++ только для заголовков, называемую cereal, которая кажется многообещающей; Разумеется, требуется компилятор, совместимый с C ++ 11. Возможно, стоит изучить и использовать его как основу для чего-то похожего boost.mpi.


Обратите внимание, что я не обязательно искал что-то, что можно было бы включить в стандарт MPI. Я полностью согласен с тем, что MPI почти всегда должен «оборачиваться каким-либо кодом более высокого уровня», так что мне интересно, как выглядит этот код более высокого уровня? У Elemental хороший подход, но лучше ли он для всех случаев? Если бы кто-то хотел иметь интерфейс C ++ к MPI, который пытался бы порадовать очень большое количество людей, как бы он выглядел?
Джефф

@Джефф. Для меня: 1. Мне нравится иметь возможность легко отправлять пользовательские типы данных. 2. Мне нравится, когда я могу с легкостью выполнять сокращение с помощью пользовательских операций. Также я думаю, что 1 я более важен / полезен, чем 2
GradGuy

Я не вижу, как C ++ делает что-то волшебное в отношении (2). Что ты здесь представляешь?
Джефф

@ Джефф Я думал что-то вроде того, как thrustэто сделать для сокращения: docs.thrust.googlecode.com/hg/group__reductions.html
GradGuy

-1

Проект github easyLambda предоставляет высокоуровневый интерфейс для MPI с C ++ 14.

Я думаю, что у проекта аналогичные цели, и он даст некоторое представление о том, что можно и нужно сделать в этой области с использованием современного C ++. Руководствуясь другими усилиями, а также самой easyLambda.

Начальные тесты производительности и строки кода показали многообещающие результаты.

введите описание изображения здесь

Ниже приведено краткое описание функций и интерфейса, который он предоставляет.

Интерфейс основан на программировании потока данных и операциях со списком функций, которые обеспечивают присущий параллелизм. Параллелизм выражается как свойство задачи. Распределение процесса и распределение данных для задачи можно запросить с помощью свойства .prll (). На веб-странице и в хранилище кодов имеется множество примеров , включающих в себя пост-обработку молекулярной динамики LAMMPS, явное конечно-разностное решение уравнения теплопроводности, логистическую регрессию и т. Д. В качестве примера обсуждается проблема диффузии тепла, рассмотренная в статье HPC ... может быть выражено в ~ 20 строк кода.

Я надеюсь, что это хорошо, чтобы дать ссылки, а не добавлять больше деталей и примеров кода здесь.

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


Вопрос гласит: « Мы ищем длинные ответы, которые дают некоторое объяснение и контекст. Не просто дайте однострочный ответ; объясните, почему ваш ответ правильный, в идеале с цитатами. Ответы, которые не включают объяснения, могут быть удалены . " Почему вы думаете, что ваш ответ достаточно полон, чтобы соответствовать этому описанию?
Никогуаро

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

@UtkarshBhardwaj: Некоторые комментарии: (1) Спасибо за написание библиотеки, которая связывает C ++ с MPI. Это важное мероприятие, и похоже, что вы вложили в него много работы. (2) Быстро просматривая документы (опять же, отличная работа), то, что выделяется, это длинные цепочки используемых методов, которые кажутся стилистически ... болезненными для отладки, даже если вы отформатировали их красиво. (3) Абстракции предполагают функциональную парадигму, которая выглядит полезной для задач, подобных уменьшению карты, но, как человек, который программирует в MPI, я не хочу переделывать свои алгоритмы и слишком далеко уходить от интерфейсов, которые я знаю.
Джефф Оксберри

(4) Я не вижу коммуникаторов в этом примере, что наводит меня на мысль, что вы используете MPI_COMM_WORLD для всего, и ограничивает потенциал вашей библиотеки. (5) Абстракции, похоже, основаны на абстракциях MPI и могут иметь другой бэкэнд. (6) Исходя из (3) - (5), я не думаю, что эта библиотека является интерфейсом MPI, и я считаю, что в результате этот комментарий не по теме.
Джефф Оксберри

@Geoff спасибо за ценный отзыв, большое спасибо. Ответ на конкретные вопросы: 2) Цепочка иногда называется ExpressionBuilder . Это распространенный способ выразить композицию в функциональном стиле. Не надо писать в этом стиле в ezl. Можно сначала написать отдельные единицы, а затем составить их, проверьте [пример] ( goo.gl/YzaL0k ). 3) Я знаю, что трудно перейти от управления потоком и обязательно к потоку данных и функционалу. У каждого есть свои плюсы и минусы. Тем не менее, я считаю, что последний должен быть изучен больше, чтобы узнать его истинную эффективность.
Utkarsh Bhardwaj
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.