Огромная разница в MPI_Wtime() после использования MPI_Barrier()?

Это часть кода.

    if(rank==0) {   
        temp=10000; 
        var=new char[temp] ;
        MPI_Send(&temp,1,MPI_INT,1,tag,MPI_COMM_WORLD); 
        MPI_Send(var,temp,MPI_BYTE,1,tag,MPI_COMM_WORLD);
            //MPI_Wait(&req[0],&sta[1]);
    }
    if(rank==1) {
        MPI_Irecv(&temp,1,MPI_INT,0,tag,MPI_COMM_WORLD,&req[0]);
        MPI_Wait(&req[0],&sta[0]);
        var=new char[temp] ;
        MPI_Irecv(var,temp,MPI_BYTE,0,tag,MPI_COMM_WORLD,&req[1]);
        MPI_Wait(&req[0],&sta[0]);
    }
    //I am talking about this MPI_Barrier


    MPI_Barrier(MPI_COMM_WORLD);
    cout << MPI_Wtime()-t1 << endl ;
    cout << "hello " << rank  << " " << temp << endl ;
        MPI_Finalize();
}

<сильный>1. при использовании MPI_Barrier - Как и ожидалось, весь процесс занимает почти одинаковое количество времени, которое составляет порядка 0,02.

<сильный>2. когда не используется MPI_Barrier() - корневой процесс (отправляющий сообщение) ждет некоторое дополнительное время. и (MPI_Wtime -t1) сильно различается, а время, затрачиваемое корневым процессом, составляет порядка 2 секунд.

Если я не ошибаюсь, MPI_Barrier используется только для приведения всех запущенных процессов на один уровень. так почему же время, когда я использую MPI_Barrier(), не составляет 2 секунды (минимум всех процессов, т.е. корневой процесс). Пожалуйста, объясни ?


person Ankur Gautam    schedule 28.06.2013    source источник
comment
Как и где вы инициализируете t1?   -  person Hristo Iliev    schedule 29.06.2013


Ответы (3)


Спасибо Уэсли Бланду за то, что он заметил, что вы дважды ждете один и тот же запрос. Вот объяснение того, что происходит на самом деле.

В MPI есть нечто, называемое последовательностью асинхронных (неблокирующих) операций. Именно тогда происходит фактическая передача. Развитие может происходить разными способами и в разных точках библиотеки MPI. Когда вы отправляете асинхронную операцию, ее выполнение может быть отложено на неопределенный срок, даже до момента вызова MPI_Wait, MPI_Test или какого-либо вызова, который приведет к тому, что новые сообщения будут помещены или извлечены из очереди передачи/получения. Вот почему очень важно вызывать MPI_Wait или MPI_Test как можно быстрее после инициирования неблокирующей операции.

Open MPI поддерживает фоновый поток выполнения, который заботится о выполнении операций, даже если условие в предыдущем абзаце не выполняется, например. если MPI_Wait или MPI_Test никогда не вызывается в дескрипторе запроса. Это должно быть явно включено при сборке библиотеки. По умолчанию он не включен, так как фоновое выполнение увеличивает задержку операций.

Что происходит в вашем случае, так это то, что вы ожидаете неправильного запроса во второй раз, когда вы вызываете MPI_Wait в приемнике, поэтому выполнение второй операции MPI_Irecv откладывается. Сообщение имеет размер более 40 КиБ (10000 раз по 4 байта + служебные данные конверта), что превышает предел ожидания по умолчанию в Open MPI (32 КиБ). Такие сообщения отправляются с использованием протокола рандеву, который требует публикации и выполнения операций отправки и получения. Операция приема не выполняется, и, следовательно, операция отправки в ранге 0 блокируется до тех пор, пока в какой-то момент времени процедуры очистки, которые вызывает MPI_Finalize в ранге 1, не завершат прием.

Когда вы помещаете вызов MPI_Barrier, это приводит к прогрессированию ожидающего получения, действуя почти как неявный вызов MPI_Wait. Вот почему отправка в ранге 0 завершается быстро, и оба процесса продолжаются во времени.

Обратите внимание, что MPI_Irecv, сразу за которым следует MPI_Wait, эквивалентно простому вызову MPI_Recv. Последний не только проще, но и менее подвержен простым опечаткам вроде той, которую вы сделали.

person Hristo Iliev    schedule 30.06.2013
comment
Спасибо за ответ. Не могли бы вы ответить на этот вопрос? модели для распределения задач в процессах с использованием openmpi">stackoverflow.com/questions/17373970/ - person Ankur Gautam; 03.07.2013

Вы ожидаете один и тот же запрос дважды для вашего Irecv. второй - это тот, который займет все время, и, поскольку его пропускают, ранг 0 уходит далеко вперед.

MPI_BARRIER может быть реализован таким образом, что некоторые процессы могут выйти из алгоритма раньше остальных, если процессы войдут в него. Вот, наверное, что здесь происходит.

person Wesley Bland    schedule 30.06.2013

В тестах, которые я запускал, я почти не вижу разницы во времени выполнения. Основное отличие состоит в том, что вы, кажется, запускаете свой код один раз, тогда как я перебирал ваш код тысячи раз, а затем брал среднее значение. Мой вывод ниже:

With the barrier
[0]: 1.65071e-05
[1]: 1.66872e-05
Without the barrier
[0]: 1.35653e-05
[1]: 1.30711e-05

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

Кроме того, почему вы используете MPI_Irecv вместе с MPI_wait, а не просто используете MPI_recv?

person SteVwonder    schedule 30.06.2013