MPI_File_read_at 逐行
MPI_File_read_at line by line
我是MPI的新手。我想使用 MPI_File_read_at() 逐行从 txt 文件中读取数据。每行的长度不同,所以当我读取一行时(设置缓冲区的长度),有时它也会读取下一行,将下一行的某些部分发送到缓冲区中,这确实会导致问题......所以,我想知道有什么方法可以使用 MPI_File_read_at() 逐行读取数据?让它在每行末尾遇到“\n”时停止?或者您有更好的建议使用 MPI_File_read_at() 以外的 MPI 函数逐行读取数据吗?
我想我的问题是如何使用 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);
}
}
MPI I/O 用于读取二进制文件,其中每条记录都由一个结构表示,因此您可以通过这种方式循环记录,或在给定位置查找记录。
但是对于文本文件,您无法提前知道每一行的位置 ends/starts。
如果你想读取一个文本文件,你需要将文件的数据传递到一个缓冲区,然后一个字符一个字符地读取数据,每当c == '\n'
,那么你现在当前行结束。
如果你只需要找到一行,仅此而已,那么你只需像我说的那样读取文件,每当一行开始时增加一个计数器,这样你就知道哪一行是你想要的。
但是如果你的程序需要多次查找它(这更有可能),一个想法是,你读一次文件,建立一个行位置的索引,然后你就可以知道在哪里每行是。
当然,如果您之后更新文件,那么您需要相应地更新索引。
编辑:你也可以看看这个answer。它在过去帮助过我。
编辑 2:你问的是什么。 MASTER 进程将文件读入一个 2D 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
我是MPI的新手。我想使用 MPI_File_read_at() 逐行从 txt 文件中读取数据。每行的长度不同,所以当我读取一行时(设置缓冲区的长度),有时它也会读取下一行,将下一行的某些部分发送到缓冲区中,这确实会导致问题......所以,我想知道有什么方法可以使用 MPI_File_read_at() 逐行读取数据?让它在每行末尾遇到“\n”时停止?或者您有更好的建议使用 MPI_File_read_at() 以外的 MPI 函数逐行读取数据吗?
我想我的问题是如何使用 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);
}
}
MPI I/O 用于读取二进制文件,其中每条记录都由一个结构表示,因此您可以通过这种方式循环记录,或在给定位置查找记录。
但是对于文本文件,您无法提前知道每一行的位置 ends/starts。
如果你想读取一个文本文件,你需要将文件的数据传递到一个缓冲区,然后一个字符一个字符地读取数据,每当c == '\n'
,那么你现在当前行结束。
如果你只需要找到一行,仅此而已,那么你只需像我说的那样读取文件,每当一行开始时增加一个计数器,这样你就知道哪一行是你想要的。
但是如果你的程序需要多次查找它(这更有可能),一个想法是,你读一次文件,建立一个行位置的索引,然后你就可以知道在哪里每行是。 当然,如果您之后更新文件,那么您需要相应地更新索引。
编辑:你也可以看看这个answer。它在过去帮助过我。
编辑 2:你问的是什么。 MASTER 进程将文件读入一个 2D 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