MPI slave отправляет данные, но только четверть из них верна - PullRequest
0 голосов
/ 27 апреля 2019

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

Я пытаюсь собрать данные, которые были распределены по моим процессорам, но только четвертая часть возвращается правильно.Я назначаю (num loops) / (num procs) количество циклов каждому процессору (пользователь вынужден использовать целое число процессоров для количества итераций).При использовании 5 процессоров и 200 итераций каждый ведомый рассчитывает все 40 значений правильно, но каким-то образом только четверть вернется к ведущему должным образом.Я увеличил его до 400 итераций, и только четверть вернулась к мастеру.Мне интересно, если мне нужно подождать или что-то, чтобы убедиться, что он заканчивает чтение с одного процессора, чтобы перейти к другому?Часть кода MPI приведена ниже со всей удаленной математикой.

#define MASTER 0
MPI_Init(NULL,NULL);
MPI_Status status;
int rank,size,name_len;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Get_processor_name(processor_name, &name_len);

chunksize = (NumEnergies / size);    
if (rank == MASTER)
{
    offset = chunksize;
    for (dest=1; dest<size; dest++)
    {
        MPI_Send(&offset, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
        offset = offset + chunksize;
    }

    //master does its calcs for CrossSections and DiffCrossSections

    for (int i=1; i<size; i++)
    {
        source = i;
        MPI_Recv(&offset, 1, MPI_INT, source, tag1, MPI_COMM_WORLD, &status);
        MPI_Recv(&CrossSections[offset][1], chunksize, MPI_DOUBLE, source, tag2, MPI_COMM_WORLD, &status);

        MPI_Recv(&DiffCrossSections[0][offset+1], (181)*chunksize, MPI_DOUBLE, source, tag3, MPI_COMM_WORLD, &status);
    }
}


if (rank > MASTER)
{
    /* Receive my portion of array from the master task */
    source = MASTER;
    MPI_Recv(&offset, 1, MPI_INT, source, tag1, MPI_COMM_WORLD, &status);

    std::cout<<"Processor: "<<processor_name<<"   rank:"<<rank<<"  Energies="<<CrossSections[offset][0]<<" - "<<CrossSections[offset+chunksize-1][0]<<std::endl;

    /* Each task does its part of the work */

    /* Send task results back to the master task */
    dest = MASTER;
    MPI_Send(&offset, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
    MPI_Send(&CrossSections[offset][1], chunksize, MPI_DOUBLE, dest, tag2, MPI_COMM_WORLD);
    MPI_Send(&DiffCrossSections[0][offset+1], (181)*chunksize, MPI_DOUBLE, dest, tag3, MPI_COMM_WORLD);
}

MPI_Finalize();

Я считал значения в каждом из ведомых, и все значения верны, хотя, конечно, перемешались.3/4 из них отправляют обратно 0, к чему я инициализирую векторы.Таким образом, кажется, что они просто сохраняют свои инициализированные значения, а не отправляют мусор.Любые подсказки относительно того, что могло заставить это возвращать только четверть значений правильно?Это четверть каждый раз, она не меняется.

Спасибо!

1 Ответ

0 голосов
/ 28 апреля 2019

Я думаю, что проблема заключалась в том, как send проходит через память, выделенную для вектора.Он отлично работает, когда я использую 1D-буфер для передачи результатов, что заставляет меня чувствовать, что данные, которые я хотел передать, были не полностью в непрерывном блоке памяти.Так что, возможно, изменение индексов при выделении вектора сделает память, к которой я хочу получить доступ, смежной.Но, пожалуй, то, что у меня есть, это договоренность «упорядоченная пара», а не то, что я на самом деле хочу, чтобы это было.Мне придется сделать то же самое для DiffCrossSections.

Редактировать: я транспонировал CrossSections и DiffCrossSections в их инициализации, и это решило проблему.Итак, похоже, что я отправлял в память данные, которые, по моему мнению, были смежными, но не были.

std::vector<std::vector<double > > DiffCrossSections (NumEnergies+1,std::vector<double>(181,0.0));
std::vector< std::vector<double > > CrossSections (2, std::vector<double> (NumEnergies,0.0));

#define MASTER 0
MPI_Init(NULL,NULL);
MPI_Status status;
int rank,size,name_len;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Get_processor_name(processor_name, &name_len);

chunksize = (NumEnergies / size);    
if (rank == MASTER)
{
    offset = chunksize;
    for (dest=1; dest<size; dest++)
    {
        MPI_Send(&offset, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
        offset = offset + chunksize;
    }

    //master does its calcs for CrossSections and DiffCrossSections

    for (int i=1; i<size; i++)
    {
        source = i;
        MPI_Recv(&offset, 1, MPI_INT, source, tag1, MPI_COMM_WORLD, &status);
        MPI_Recv(&CorssSections[1][offset], chunksize, MPI_DOUBLE, source, tag2, MPI_COMM_WORLD, &status);

        MPI_Recv(&DiffCrossSections[offset+1][0], (181)*chunksize, MPI_DOUBLE, source, tag3, MPI_COMM_WORLD, &status);
    }
}


if (rank > MASTER)
{
    /* Receive my portion of array from the master task */
    source = MASTER;
    MPI_Recv(&offset, 1, MPI_INT, source, tag1, MPI_COMM_WORLD, &status);

    std::cout<<"Processor: "<<processor_name<<"   rank:"<<rank<<"  Energies="<<CrossSections[0][offset]<<" - "<<CrossSections[0][offset+chunksize-1]<<std::endl;

    /* Each task does its part of the work */

    /* Send task results back to the master task */
    dest = MASTER;
    MPI_Send(&offset, 1, MPI_INT, dest, tag1, MPI_COMM_WORLD);
    MPI_Send(&CrossSections[1][offset], chunksize, MPI_DOUBLE, dest, tag2, MPI_COMM_WORLD);
    MPI_Send(&DiffCrossSections[offset+1][0], (181)*chunksize, MPI_DOUBLE, dest, tag3, MPI_COMM_WORLD);
}

MPI_Finalize();
...