Запись в несколько общих файлов с помощью MPI-IO

Я запускаю симуляцию с тысячами процессов MPI и мне нужно записать выходные данные в небольшой набор файлов. Например, хотя у меня может быть 10000 процессов, я хочу записать только 10 файлов, по 1000 записей в каждый (с некоторым подходящим смещением). AFAIK правильный способ сделать это - создать новый коммуникатор для групп процессов, которые будут записывать в одни и те же файлы, открыть общий файл для этого коммуникатора с помощью MPI_File_open(), а затем написать ему MPI_File_write_at_all(), Это верно? Следующий код представляет собой игрушечный пример, который я написал:

#include <mpi.h>
#include <math.h>
#include <stdio.h>

const int MAX_NUM_FILES = 4;

int main(){
    MPI_Init(NULL, NULL);

    int rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    int numProcs;
    MPI_Comm_size(MPI_COMM_WORLD, &numProcs);

    int numProcsPerFile = ceil(((double) numProcs) / MAX_NUM_FILES);
    int targetFile = rank / numProcsPerFile;

    MPI_Comm fileComm;
    MPI_Comm_split(MPI_COMM_WORLD, targetFile, rank, &fileComm);

    int targetFileRank;
    MPI_Comm_rank(fileComm, &targetFileRank);

    char filename[20]; // Sufficient for testing purposes
    snprintf(filename, 20, "out_%d.dat", targetFile);
    printf(
        "Proc %d: writing to file %s with rank %d\n", rank, filename,
        targetFileRank);

    MPI_File outFile;
    MPI_File_open(
        fileComm, filename, MPI_MODE_CREATE | MPI_MODE_WRONLY,
        MPI_INFO_NULL, &outFile);

    char bufToWrite[4];
    snprintf(bufToWrite, 4, "%3d", rank);

    MPI_File_write_at_all(
        outFile, targetFileRank * 3,
        bufToWrite, 3, MPI_CHAR, MPI_STATUS_IGNORE);

    MPI_File_close(&outFile);
    MPI_Finalize();
}

Я могу скомпилировать mpicc file.c -lm и запустить, скажем, 20 процессов с mpirun -np 20 a.out, и я получаю ожидаемый результат (четыре файла с пятью записями в каждом), но я не уверен, является ли это технически правильным / наиболее оптимальным способом сделать это. Что-нибудь, что я должен сделать по-другому?

3 ответа

Решение

Ваш подход правильный. Чтобы уточнить, нам нужно пересмотреть стандарт и определения. MPI_File_Open API из MPI: стандарт интерфейса передачи сообщений версии 2.2 (стр. 391)

int MPI_File_open (MPI_Comm comm, char * имя файла, int amode, информация MPI_Info, MPI_File *fh)

Описание:

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

интракоммуникатор против интеркоммуникатора (стр. 134):

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

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

MPI_Comm_Split() в мощном API, который позволяет разбить взаимодействующую группу на непересекающиеся подгруппы для использования в различных случаях использования, включая ввод / вывод MPI.

Я думаю, что это, вероятно, опечатка выше, но это "_all", что означает коллективную операцию.

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

MPI_File_write_at_all должен быть наиболее эффективным способом сделать это. Функции коллективного ввода-вывода обычно бывают самыми быстрыми для больших несмежных параллельных записей в общий файл, а вариант _all объединяет поиск и запись в один вызов.

Другие вопросы по тегам