2012-03-19 15 views
5

Mam ogromną matrycę, którą podzieliłem na pewne pod macierze i wykonuję na niej pewne obliczenia. Po tych obliczeniach muszę zapisać tę macierz w jednym pliku do przetwarzania końcowego. Czy można zapisać wyniki w jednym pliku tekstowym i jak mogę to zrobić? Na przykład mamy nx ny macierz, która jest podzielona na kierunek y (każdy proces ma matrycę rx) i chcemy zapisać macierz nx * ny w jednym pliku tekstowym.zapisywanie macierzy w jeden plik txt z mpi

+2

Wystarczy popatrzeć na MPI-IO http://beige.ucs.indiana.edu/I590/node86.html –

Odpowiedz

12

Dlatego nie jest dobrym pomysłem zapisywanie dużych ilości danych jako tekstu. Jest naprawdę, naprawdę, powolny, generuje niepotrzebnie duże pliki i jest to trudny do opanowania. Duże ilości danych powinny być zapisane jako binarne, a jedynie dane zbiorcze dla ludzi zapisane jako tekst. Twórz rzeczy, którymi komputer będzie się zajmował z łatwością dla komputera, i tylko te rzeczy, które faktycznie usiądziesz i przeczytasz w łatwy sposób (np. Tekst).

Niezależnie od tego, czy zamierzasz pisać jako tekst, czy jako plik binarny, możesz użyć MPI-IO do skoordynowania danych wyjściowych z plikiem, aby wygenerować jeden duży plik. Mamy mały samouczek na ten temat (używając MPI-IO, HDF5 i NetCDF) here. W przypadku MPI-IO trik polega na zdefiniowaniu typu (tutaj, podwielokrotności) w celu opisania lokalnego układu danych pod względem globalnego układu pliku, a następnie zapisania do pliku z użyciem tego jako "widoku". Każdy plik widzi tylko własny widok, a biblioteka MPI-IO koordynuje dane wyjściowe, więc dopóki widoki nie zachodzą na siebie, wszystko wychodzi jako jeden duży plik.

Gdybyśmy pisali to w formacie binarnym, wskazywalibyśmy MPI_Write na nasze dane i robimy z tym; ponieważ używamy tekstu, musimy przekonwertować dane na ciąg znaków. Definiujemy naszą tablicę tak, jak normalnie, z wyjątkiem tego, że jest to MPI_FLOATs, jest nowego typu, który jest liczbą charspernum na liczbę.

Kod następująco:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <mpi.h> 

float **alloc2d(int n, int m) { 
    float *data = malloc(n*m*sizeof(float)); 
    float **array = malloc(n*sizeof(float *)); 
    for (int i=0; i<n; i++) 
     array[i] = &(data[i*m]); 
    return array; 
} 

int main(int argc, char **argv) { 
    int ierr, rank, size; 
    MPI_Offset offset; 
    MPI_File file; 
    MPI_Status status; 
    MPI_Datatype num_as_string; 
    MPI_Datatype localarray; 
    const int nrows=10; 
    const int ncols=10; 
    float **data; 
    char *const fmt="%8.3f "; 
    char *const endfmt="%8.3f\n"; 
    int startrow, endrow, locnrows; 

    const int charspernum=9; 

    ierr = MPI_Init(&argc, &argv); 
    ierr|= MPI_Comm_size(MPI_COMM_WORLD, &size); 
    ierr|= MPI_Comm_rank(MPI_COMM_WORLD, &rank); 

    locnrows = nrows/size; 
    startrow = rank * locnrows; 
    endrow = startrow + locnrows - 1; 
    if (rank == size-1) { 
     endrow = nrows - 1; 
     locnrows = endrow - startrow + 1; 
    } 

    /* allocate local data */ 
    data = alloc2d(locnrows, ncols); 

    /* fill local data */ 
    for (int i=0; i<locnrows; i++) 
     for (int j=0; j<ncols; j++) 
      data[i][j] = rank; 

    /* each number is represented by charspernum chars */ 
    MPI_Type_contiguous(charspernum, MPI_CHAR, &num_as_string); 
    MPI_Type_commit(&num_as_string); 

    /* convert our data into txt */ 
    char *data_as_txt = malloc(locnrows*ncols*charspernum*sizeof(char)); 
    int count = 0; 
    for (int i=0; i<locnrows; i++) { 
     for (int j=0; j<ncols-1; j++) { 
      sprintf(&data_as_txt[count*charspernum], fmt, data[i][j]); 
      count++; 
     } 
     sprintf(&data_as_txt[count*charspernum], endfmt, data[i][ncols-1]); 
     count++; 
    } 

    printf("%d: %s\n", rank, data_as_txt); 

    /* create a type describing our piece of the array */ 
    int globalsizes[2] = {nrows, ncols}; 
    int localsizes [2] = {locnrows, ncols}; 
    int starts[2]  = {startrow, 0}; 
    int order   = MPI_ORDER_C; 

    MPI_Type_create_subarray(2, globalsizes, localsizes, starts, order, num_as_string, &localarray); 
    MPI_Type_commit(&localarray); 

    /* open the file, and set the view */ 
    MPI_File_open(MPI_COMM_WORLD, "all-data.txt", 
        MPI_MODE_CREATE|MPI_MODE_WRONLY, 
        MPI_INFO_NULL, &file); 

    MPI_File_set_view(file, 0, MPI_CHAR, localarray, 
          "native", MPI_INFO_NULL); 

    MPI_File_write_all(file, data_as_txt, locnrows*ncols, num_as_string, &status); 
    MPI_File_close(&file); 

    MPI_Type_free(&localarray); 
    MPI_Type_free(&num_as_string); 

    free(data[0]); 
    free(data); 

    MPI_Finalize(); 
    return 0; 
} 

Bieg daje:

$ mpicc -o matrixastxt matrixastxt.c -std=c99 
$ mpirun -np 4 ./matrixastxt 
$ more all-data.txt 
    0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 
    0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 
    1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 
    1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 1.000 
    2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 
    2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 2.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
    3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 3.000 
+0

podziękowaniem za twoją odpowiedź. – peaceman

+0

Właśnie przeżyłem twoją prezentację, bardzo pouczającą i intuicyjną! Dziękuję Ci – solalito

Powiązane problemy