2016-03-14 5 views
1

Я передаю большие векторы между процессами для численного моделирования. Все работает нормально до определенного временного шага. Я не получаю ошибок, но выходное решение явно неверно.Общая проблема связи MPI

Я отлаживаю довольно долгое время, и мое предположение заключается в том, что в сообщении MPI есть ошибка.

Связь часть моего кода выглядит следующим образом:

MPI_Request req; 
for(int j=0;j<numProcs;j++){ 
    if(j!=myId){ 
     tag=0; 
     sizeToSend=toProc[j].size(); 
     MPI_Isend(&sizeToSend, 1, MPI_LONG_LONG, j, tag, MPI_COMM_WORLD,&req); 
     MPI_Request_free(&req); 
    } 
} 
for(int j=0;j<numProcs;j++){ 
    if(j!=myId){ 
     tag=0; 
     MPI_Recv(&sizeToReceive[j], 1, MPI_LONG_LONG, j, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    } 
} 
for(int j=0;j<numProcs;j++){ 
    if(j!=myId){ 
     if(toProc[j].size()>0){ 
      tag=1; 
      MPI_Isend(&toProc[j][0], toProc[j].size(), MPI_LONG_LONG, j, tag, MPI_COMM_WORLD,&req); 
      MPI_Request_free(&req); 
     } 
    } 
} 
for(int j=0;j<numProcs;j++){ 
    if(j!=myId){ 
     if(sizeToReceive[j]>0){ 
      receiveBuffer.resize(sizeToReceive[j]); 
      tag=1; 
      MPI_Recv(&receiveBuffer[0], sizeToReceive[j], MPI_LONG_LONG, j, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
      for(int k=0;k<sizeToReceive[j];k++){ 
       domain.field[receiveBuffer[k]]=1; 
      } 
      receiveBuffer.clear(); 
     } 
    } 
} 
MPI_Barrier(MPI_COMM_WORLD); 
for(int j=0;j<toProc.size();j++){ 
    toProc[j].clear(); 
} 

Переменная numProcs является ИНТ, содержащий число процессов, myId является INT, содержащий ранг процессов, tag является INT, domain.field является a vector<char>. Другие необходимые переменные определены следующим образом:

vector<vector <long long> > toProc; 
toProc.resize(numProcs); 
long long sizeToReceive[numProcs]; 
long long sizeToSend=0; 
vector<long long> receiveBuffer; 

То, что я пытаюсь сделать в коде выше, чтобы отправить векторы toProc[j] для обработки с id==j for j=0,...,numProcs-1, j!=myId на каждом процессе. Для этого я отправляю и получаю размеры этих векторов в первых двух циклах for-loops и отправляю и получаю фактические данные в 3-м и 4-м циклах. Я использую Isend, потому что я, очевидно, хочу, чтобы эти вызовы были неблокирующими.

Значения в toProc[j] - это индексы, которые должны быть установлены в поле vector domain.field в процессе j (каждый процесс имеет свое собственное доменное поле).

Мой вопрос: Вы видите какой-либо потенциал для неожиданного поведения при использовании политики Isend-Recv.

+1

Я не вижу немедленной проблемы, кроме того, возможно, рассылает слишком много текущих запросов, но, похоже, вы могли бы значительно упростить и ускорить всю операцию с помощью MPI_Alltoall и MPI_Alltoallv. – Zulan

+0

Спасибо за предложение, я попытаюсь реализовать то же поведение, используя 'MPI_Alltoall', сколько запросов вы считаете слишком много? Ошибка также возникает, если я использую только 4 процесса, может быть, это уже слишком много? – Jonas

+0

Кажется, я упустил из виду довольно очевидную проблему, пожалуйста, см. Мой ответ. – Zulan

ответ

2

Вы повторно используете переменную для нескольких запросов ISend, не дожидаясь завершения.

MPI Standard: 3.7.2 и 3.7.4 о MPI_Request_free

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

Это означает, что вы не должны перезаписывать sizeToSend перед отправкой.

Отметьте объект запроса для освобождения и задайте запрос MPI_REQUEST_NULL. Постоянное сообщение, связанное с запросом , будет завершено. Запрос будет освобожден только после его завершения.

Это значит, что после MPI_Request_free это сообщение не гарантируется.

Вы можете перестроить свой код, чтобы сохранить sizeToSend в векторе, а также сохранить открытые запросы в векторе правильно MPI_Waitall на них. Но я бы посоветовал просто использовать MPI_Alltoall и MPI_Alltoallv для всей операции.

+0

Спасибо за ваши предложения, я внедрил общение так, как вы предлагали. Это не решает мою проблему, но, по крайней мере, у меня синхронная связь, и я могу предположить, что ошибка должна быть где-то в другом месте. – Jonas

+0

@Jonas Если вы можете воспроизвести другую проблему с помощью небольшого примера, можете открыть другой вопрос. Вы также можете дать [ДОЛЖНО] (https://doc.itc.rwth-aachen.de/display/CCP/Project+MUST) попробовать - это проверка правильности MPI. – Zulan

+0

Я нашел свою ошибку, она не имела ничего общего с MPI .. она находилась в строке 'domain.field [receiveBuffer [k]] = 1;', для 'receiveBuffer [k]' должно существовать дифференциация case. Но я мог только найти его, потому что я внедрил эту часть, немного отличающуюся при использовании вашего «MPI_Alltoall», и ошибка получилась иной. Поэтому, хотя ваше предложение не указывало на фактическую ошибку, которую я искал, это помогло значительно ее обнаружить (и улучшило мой код). Так что еще раз спасибо, миссия выполнена :) – Jonas

Смежные вопросы