Запись в несколько общих файлов с помощью 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 объединяет поиск и запись в один вызов.