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