Мое приложение C++ Unix/окон уже параллелизируется с помощью MPI: задание является splitted в CPU N, и каждый блок выполняется параллельно, довольно эффективное, очень хорошее масштабирование скорости, задание сделано правильно.
Но некоторые данные повторяются в каждом процессе, и для технических причин эти данные не могут быть легко splitted по MPI (...). Например:
На 4 заданиях ЦП это означало бы, по крайней мере, загрузку RAM на 20 ГБ, большая часть 'потраченной впустую' памяти, это ужасно.
Я думаю с помощью общей памяти для сокращения полной нагрузки, "статический" блок был бы загружен только однажды на компьютер.
Так, основной вопрос:
Действительно ли там кто-либо - стандартный способ MPI совместно использовать память на узле? Некоторое легко доступное + свободная библиотека?
boost.interprocess
и используйте вызовы MPI для распределения локальных идентификаторов общей памяти.Какой-либо хит производительности или конкретные вопросы для опасаний?
Задание будет выполняться в PBS (или SGE), система массового обслуживания, в случае процесса грязный выход, интересно, будут ли они очистка определенная для узла общая память.
Одним из все более распространенных подходов в High Performance Computing (HPC) являются гибридные MPI/OpenMP программы. Т.е. у вас есть N MPI-процессов, и каждый MPI-процесс имеет M-потоков. Этот подход хорошо подходит для кластеров, состоящих из многопроцессорных узлов с общей памятью.
Изменение такой иерархической схемы распараллеливания, очевидно, требует некоторых более или менее инвазивных изменений, OTOH, при правильном выполнении, может повысить производительность и масштабируемость кода, а также снизить потребление памяти для реплицируемых данных.
В зависимости от реализации MPI, вы можете быть в состоянии, а можете и не быть в состоянии выполнять вызовы MPI из всех потоков. Это указано в аргументах required
и provided
для функции MPI_Init_Thread(), которые необходимо вызывать вместо MPI_Init(). Возможными значениями являются
{ MPI_THREAD_SINGLE} Only one thread will execute. { MPI_THREAD_FUNNELED} The process may be multi-threaded, but only the main thread will make MPI calls (all MPI calls are ``funneled'' to the main thread). { MPI_THREAD_SERIALIZED} The process may be multi-threaded, and multiple threads may make MPI calls, but only one at a time: MPI calls are not made concurrently from two distinct threads (all MPI calls are ``serialized''). { MPI_THREAD_MULTIPLE} Multiple threads may call MPI, with no restrictions.
По моему опыту, современные реализации MPI, такие как Open MPI, поддерживают наиболее гибкую MPI_THREAD_MULTIPLE. Если вы используете старые библиотеки MPI или какую-то специализированную архитектуру, то вам может быть хуже.
Конечно, вам не нужно выполнять потоковую работу с OpenMP, это просто самый популярный вариант в HPC. Для этого можно использовать, например, библиотеку Boost threads, библиотеку Intel TBB или прямые pthreads или windows threads
.С MPI-2 вы получаете RMA (удаленный доступ к памяти) через такие функции, как MPI_Put и MPI_Get. Использование этих функций, если ваша установка MPI поддерживает их, безусловно, поможет вам снизить общее потребление памяти вашей программой. Стоит добавить сложность в кодировании, но это часть удовольствия от параллельного программирования. И опять же, это держит вас в области MPI.
.У меня было несколько проектов с MPI в SHUT.
Как я знаю, есть много способов распространять проблему, используя MPI, может быть, вы сможете найти другое решение, которое не требует совместного использования памяти, в моем проекте решалось уравнение 7,000,000 и переменная 7,000,000
, если вы сможете объяснить вашу проблему, я постараюсь вам помочь
.Я не работал с MPI, но если это похоже на другие IPC библиотеки, которые я видел, что скрывают, находятся ли другие потоки/процессы/что-либо на той же или другой машине, то это не сможет гарантировать общий доступ к памяти. Да, он может работать с разделяемой памятью между двумя узлами на одной машине, если эта машина сама предоставляет разделяемую память. Но пытаться совместно использовать память между узлами на разных машинах будет в лучшем случае очень сложно, из-за сложных проблем с когерентностью. Я бы ожидал, что это будет просто нереализованно.
Во всей практичности, если вам нужно совместно использовать память между узлами, лучше всего делать это за пределами MPI. Я не думаю, что вам нужно использовать boost. interprocess
-стиль разделяемой памяти, т.к. вы не описываете ситуацию, когда различные узлы вносят мелкие изменения в разделяемую память; она либо доступна только для чтения, либо разбита на разделы.
Ответы Джона и Деуса рассказывают о том, как отобразить в файле, что определённо нужно для 5 Гб (gigabit?) статических данных. Данные на каждую центральную процессорную установку звучат одинаково, и вам просто нужно послать сообщение каждому узлу, говоря ему, какую часть файла он должен захватить. Операционная система должна позаботиться о преобразовании виртуальной памяти в физическую в файлах.
Что касается очистки...? Я бы предположил, что она не делает никакой очистки разделяемой памяти, но файлы mmap
ed должны быть очищены, так как при очистке процесса файлы закрываются (что должно освободить их отображение в памяти). Понятия не имею, какие предупреждения имеются в CreateFileMapping
и т.д.
Актуальная "разделяемая память" (т.е. boost.interprocess
) не очищается при завершении процесса. Если возможно, я бы порекомендовал попробовать убить процесс и посмотреть, что осталось.
Я мало что знаю об unix, и я не знаю, что такое MPI. Но в Windows то, что вы описываете, точно совпадает с объектом отображения файлов.
Если эти данные вложены в вашу .EXE или загружаемую ею .DLL, то они будут автоматически распределены между всеми процессами. Утечка данных из вашего процесса, даже в результате сбоя, не приведет к утечкам или невыпущенным блокировкам ваших данных. Однако 9Гб .dll звучит немного сомнительно. Поэтому, вероятно, это не сработает для вас.
Однако, вы можете поместить ваши данные в файл, затем CreateFileMapping
и MapViewOfFile
на нем. Карта может быть считана только для чтения, и вы можете поместить все или часть файла в память. Все процессы будут разделять страницы, которые отображаются одинаково, как и базовый объект CreateFileMapping. Хорошей практикой является закрытие представлений unmap и закрытие дескрипторов, но если вы этого не сделаете, операционная система сделает это за вас в режиме просмотра.
Обратите внимание, что если вы не используете x64, вы не сможете отобразить 5Гб файл в одном виде (или даже 2Гб файл, 1Гб может сработать). Но учитывая, что вы говорите о том, что это уже работает, я предполагаю, что вы уже только x64.
.Если Вы храните свои статические данные в файле, Вы можете использовать mmap на unix для получения случайного доступа к данным. Данные будут вызываться по мере и когда Вам понадобится доступ к определённому битовому элементу данных. Всё, что вам нужно будет сделать, это наложить любые бинарные структуры на данные файла. Это unix-эквивалент описанных выше CreateFileMapping и MapViewOfFile.
Кстати, glibc использует mmap при вызове malloc для запроса более одной страницы данных.
.Я столкнулся с этой проблемой в малой степени, когда использовал MPI несколько лет назад.
Я не уверен, что SGE понимает файлы mapped памяти. Если вы распространяетесь против beowulf cluster, я подозреваю, что у вас будут проблемы с когерентностью. Не могли бы вы немного обсудить вашу многопроцессорную архитектуру?
Мой черновой подход будет заключаться в настройке архитектуры, где каждая часть данных принадлежит определенному процессору. Там было бы два потока: один поток был бы MPI двусторонним и один поток для вычисления результата. Обратите внимание, что MPI и потоки не всегда хорошо играют вместе
.