2015-11-16 3 views
1

Я пытаюсь собрать массивы различных размеров, используя MPI_Gatherv, но по какой-то причине он собирает только первый объект в первом процессоре. Когда я делаю цикл выше, я получаю правильные значения от xPos и ​​yPos, но когда я собираю данные в массив xFinal и yFinal и распечатываю значения, я получаю только первые x и y. Таким образом, в основном первый объект имеет (x, y) of (0,0), и у меня есть 10 объектов, и все объекты только распечатывают (0,0), когда фактический объект, на который он должен ссылаться, имеет разные (x, y)MPI_Gatherv не собирает данные правильно

На всякий случай, чтобы сказать, графы [ранг] и вытеснения определенно правы, потому что я использовал их для рассеивания ранее.

Я использую сборщик неправильно? Или я печатаю неправильно?

for (a = 0; a < size; a++) { 
    if (rank == a) { 
     for (i = 0 ; i < counts[rank]; i++) { 
      printf("from procs %d: %lE %lE\n", rank, xPos[i], yPos[i]); 
     } 
    } 
} 


MPI_Gatherv(&xPos, counts[rank], MPI_DOUBLE, &xFinal, counts, displs, MPI_DOUBLE,0, MPI_COMM_WORLD); 
MPI_Gatherv(&yPos, counts[rank], MPI_DOUBLE, &yFinal, counts, displs, MPI_DOUBLE,0, MPI_COMM_WORLD); 


MPI_Finalize(); 

FILE* f = fopen("universe.out", "wt"); 
for (i = 0; i < N; i++) 
    fprintf(f, "%lE %lE\n", xFinal[i], yFinal[i]); 
fclose(f); 

ответ

2

Кажется, что вы пишете файл со всех рангов одновременно. Вы должны поместить код файла письма в if (rank == 0) { ... } только пусть ранга 0 запись:

if (rank == 0) 
{ 
    FILE* f = fopen("universe.out", "wt"); 
    for (i = 0; i < N; i++) 
     fprintf(f, "%lE %lE\n", xFinal[i], yFinal[i]); 
    fclose(f); 
} 

В противном случае содержимое файла может быть что угодно.

+0

Вау, это спасло мне жизнь! Это не полностью решило мои проблемы, потому что в итоге я перешел в некоторые странные параметры со ссылками, которые дали мне сумасшедшие номера (которые я исправил), но это, наконец, позволило мне увидеть некоторые цифры в файле! Спасибо огромное! – Amanda

0

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

Во-первых, текстовый формат вывода действительно то, что вы (и ваши сотрудники) хотите? если univers.out становится настолько большим, что вы хотите прочитать его параллельно, у вас будет вызов для разложения файла на всех процессорах. Рассмотрим параллельные HDF5 (phdf5) или paralllel-netcdf (pnetcdf) или любые другие библиотеки более высокого уровня с самоописывающимся портативным файловым форматом.

Вот пример того, как вы выписываете все значения x, а затем все значения y.

#include <stdio.h> 
#include <mpi.h> 
#include <unistd.h> //getpid 
#include <stdlib.h> //srandom, random 

#define MAX_PARTS 10 

int main(int argc, char **argv) { 
    int rank, nprocs; 
    MPI_Offset nparts; // more than 2 billion particle possible 
    int i; 
    double *x, *y; 
    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &nprocs); 
    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    MPI_Offset start=0, x_end; 
    MPI_Info info; 
    MPI_File fh; 
    MPI_Status status; 
    srandom(getpid()); 

    /* demonstrate this works even when particles are not evenly 
* distributed over the processes */ 
    nparts=((double)random()/RAND_MAX)*MAX_PARTS; 

    x = malloc(nparts*sizeof(*x)); 
    y = malloc(nparts*sizeof(*y)); 
    for (i = 0; i< nparts; i++) { 
     /* just some bogus data to see what happens */ 
     x[i] = rank*100+i; 
     y[i] = rank*200+i; 
    } 

    /* not using this now. might tune later if needed */ 
    MPI_Info_create(&info); 

    MPI_File_open(MPI_COMM_WORLD, "universe.out", 
    MPI_MODE_CREATE|MPI_MODE_WRONLY, info, &fh); 
    MPI_File_set_view(fh, 0, MPI_DOUBLE, MPI_DOUBLE, "native", info); 

    MPI_Scan(&nparts, &start, 1, MPI_OFFSET, MPI_SUM, MPI_COMM_WORLD); 

    /* MPI_Scan is a prefix reduction: remove our contribution */ 
    x_end = start; /* only the last rank will use this in the bcast below */ 
    start -= nparts; 

    MPI_Bcast(&x_end, 1, MPI_OFFSET, nprocs-1, MPI_COMM_WORLD); 
    MPI_File_write_at_all(fh, start, x, nparts, MPI_DOUBLE, &status); 
    MPI_File_write_at_all(fh, start+x_end, y, nparts, MPI_DOUBLE, &status); 

    MPI_Info_free(&info); 
    MPI_File_close(&fh); 

    MPI_Finalize(); 

} 

Выписывая х массив и у массива в качестве пара (х, у) значений возможно, но немного сложнее (Вы должны сделать тип данных MPI).

У Parallel-NetCDF есть оптимизация «комбинирования операций», которая делает это для вас. Parallel-HDF5 имеет оптимизацию «multi-dataset i/o» в работах для следующего выпуска. С помощью этих оптимизаций вы можете определить 3d-массив с одним измерением для x и y и третьим для «идентификатора частиц». Затем вы можете опубликовать операцию для значений x, операцию для значений y и , чтобы позволить библиотеке объединить все это в один вызов.