MPI_File_read_at построчно

Я новый ученик MPI. Я хотел бы использовать MPI_File_read_at() для чтения данных из текстового файла построчно. Длина каждой строки различна, поэтому, когда я читаю одну строку (задаю длину буфера), иногда он также читает следующую строку, отправляет некоторую часть следующей строки в буфер, что действительно вызывает проблемы... Итак, мне интересно, есть ли способ использовать MPI_File_read_at() для чтения данных построчно? чтобы он остановился, когда встретил "\n" в конце каждой строки? Или у вас есть лучшее предложение читать данные построчно, используя функцию MPI, отличную от MPI_File_read_at()?

Я думаю, мой вопрос заключается в том, как использовать MPI_File_read_at(), чтобы сделать то же самое, что делает fgets

/*the traditional way to read a file line by line:*/
for(i=0;i<nlens;i++)
{
    fgets(line, 20, fp);
    sscanf(line,"%d%d",&e1,&e2);
}


/*the way I am doing this by MPI*/

int offset = 0;
int count = 15;
char line[15];
for(i=0;i<nlens;i++)
{
    offset=i*count;
    MPI_File_read_at(fp, offset, line, count, MPI_CHAR, &status);
    printf("line%d:/n%s/n",i,line);
}

/*So, if I have a file looks like:*/
0        2
0        44353
3        423
4        012312
5        2212
5        476

/*the output of mpi version  will be:*/
line0: 
0        2
0
line1:
      44353
3
line2:
      423
4
line3:
    012312
5
line4:
      2212
5
line5:
     476
2
5

void read_data(char address_data[], int num_edges, int link[][100])
{
    int i,e1,e2;
    FILE *fp;
    char line[30];

    int totalTaskNum, rankID;
    MPI_Comm_rank(MPI_COMM_WORLD, &rankID);
    MPI_Comm_size(MPI_COMM_WORLD, &totalTaskNum);
    MPI_Status status;
    if(rankID == 0)  /*to avoid different processors access to the file simultaneously*/
    {
        fp = fopen(address_data, "r");
        for(i=0;i<num_edges;i++)
        {
            fgets(line, 20, fp);
            sscanf(line,"%d%d",&e1,&e2);
            link[e1][e2]++;
        }
        fclose(fp);
    }
}

1 ответ

Решение

MPI I/O предназначен для чтения двоичных файлов, где каждая запись представлена ​​структурой, поэтому вы можете зацикливать записи или находить запись в заданной позиции.

Но с текстовыми файлами вы не можете знать заранее, где заканчивается каждая строка.

Если вы хотите прочитать текстовый файл, вам нужно будет передать данные этого файла в буфер, а затем прочитать данные char на char и всякий раз, когда c == '\n', тогда вы теперь, когда текущая строка заканчивается.

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

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

Изменить: вы также можете взглянуть на этот ответ. Это помогло мне в прошлом.

Редактировать 2: что вы спросили. Процесс MASTER считывает файл в двумерный массив int.

я создаю файл matrix.txt и я разместил это space separated ценности:

0 2
0 44353
3 423
4 012312
5 2212
5 476

Вот программа:

#include <mpi.h>

#define FILENAME    "matrix.txt"
#define WIDTH       2
#define HEIGHT      6


int main() {

    int rank, world_size;

    MPI_Init(NULL, NULL);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);


    int matrix[HEIGHT][WIDTH];

    /**
     * The MASTER process reads the file
     */
    if (rank == 0) { 
        FILE *fp = fopen(FILENAME, "r");

        char line[100];
        int i = 0;
        while (fgets(line, 100, fp)) {
            sscanf(line, "%d %d", &matrix[i][0], &matrix[i][1]);
            i++;
        }
    }

    //Broadcast it to all processes
    MPI_Bcast(matrix, HEIGHT * WIDTH, MPI_INT, 0, MPI_COMM_WORLD);

    //just for demo purposes each process prints its array orderly
    int p = 0, i = 0, j = 0;
    for (p = 0; p < world_size; p++) {
        MPI_Barrier(MPI_COMM_WORLD);
        if (p == rank) {
            printf("----------\n proc:%d received:\n", rank);
            for (i = 0; i < HEIGHT; i++) {
                for (j = 0; j < WIDTH; j++) {
                    printf("%d\t", matrix[i][j]);
                }
                printf("\n");
            }
        }
    }


    MPI_Finalize();
    return 0;
}

Я сделал несколько предположений, например, что вы заранее знаете размер матрицы в файле. Если вы хотите сделать вашу программу более динамичной, я оставлю это на ваше усмотрение. Также после прочтения файла я транслирую матрицу на весь процесс, чтобы вы могли проверить, работает ли он. так как вы говорите, что хотите сделать матричное умножение, вам нужно будет следовать стратегии разложения, используя MPI_Scatter или что-то еще, чтобы каждый процесс получал свой фрагмент.

Вот вывод:

$ mpirun -np 4 ./program 
----------
 proc:0 received:
0       2       
0       44353   
3       423     
4       12312   
5       2212    
5       476     
----------
 proc:1 received:
0       2       
0       44353   
3       423     
4       12312   
5       2212    
5       476     
----------
 proc:2 received:
0       2       
0       44353   
3       423     
4       12312   
5       2212    
5       476     
----------
 proc:3 received:
0       2       
0       44353   
3       423     
4       12312   
5       2212    
5       476     
Другие вопросы по тегам