запись матрицы в один текстовый файл с MPI - PullRequest
6 голосов
/ 20 марта 2012

У меня есть огромная матрица, я разделил ее на несколько подматриц и произвел некоторые вычисления на ней. После этих вычислений я должен записать эту матрицу в один файл для последующей обработки. Можно ли записать результаты в один текстовый файл и как я могу это сделать? Например, у нас есть матрица nx ny, которая делится в направлении y (каждый процесс имеет матрицу ранга nx ), и мы хотим записать матрицу nx * ny в один текстовый файл.

1 Ответ

12 голосов
/ 21 марта 2012

Так что не стоит писать большие объемы данных в виде текста. Он действительно очень медленный, он генерирует ненужные большие файлы, и с этим трудно справиться. Большие объемы данных должны быть записаны в двоичном виде, а только сводные данные для людей записаны в виде текста. Сделайте вещи, с которыми будет работать компьютер, легкой для компьютера, и только те вещи, которые вы на самом деле собираетесь сесть и прочитать, с которыми вам будет легко иметь дело (например, текст).

Независимо от того, собираетесь ли вы писать в текстовом или двоичном формате, вы можете использовать MPI-IO для согласования выходных данных с файлом для создания одного большого файла. У нас есть небольшое руководство по этой теме (с использованием MPI-IO, HDF5 и NetCDF) здесь . Для MPI-IO хитрость заключается в том, чтобы определить тип (здесь подрешетка), чтобы описать локальный макет данных в терминах глобального макета файла, а затем записать в файл, используя его в качестве «представления». Каждый файл видит только свое собственное представление, а библиотека MPI-IO координирует вывод так, что, пока представления не перекрываются, все получается как один большой файл.

Если бы мы записывали это в двоичном виде, мы бы просто указали MPI_Write на наши данные и покончили с этим; так как мы используем текст, мы должны преобразовать данные в строку. Мы определяем наш массив так, как мы обычно это делаем, за исключением того, что вместо MPI_FLOAT он имеет новый тип charspernum символов на число.

Код следует:

#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;
}

Бег дает:

$ 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...