引数は、ではなくmyfile
タイプの変数であるため、、などに使用することはできません。これがおそらくセグメンテーション違反の原因です。MPI_File
FILE *
fgets()
rewind()
私の提案は、この回答のアプローチを採用し、ファイルごとに重複するチャンクを読み取ることです(行の長さがわからないという事実を考慮して)、各タスクはチャンクとプロセスtheir
行を読み取ります。各ファイルの行数が(可能な限り)まったく同じであることに本当に関心がある場合は、ファイル間でデータを交換して、正確に同じ行数にすることができます。
更新:本当にこれを実行したい場合(入力がすべて数値の場合、これはバイナリ形式で非常に簡単になることに注意してください)、テキストファイルを読み取り、他の数値と同じようにパーティションを作成し、それぞれを処理するコード行(たとえば、列を合計することによる)は、上記でリンクした回答からの単純な拡張として続きます。
#include <stdio.h>
#include <mpi.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
void readlines(MPI_File *in, const int rank, const int size, const int overlap,
char ***lines, int *nlines) {
MPI_Offset filesize;
MPI_Offset localsize;
MPI_Offset start;
MPI_Offset end;
char *chunk;
/* figure out who reads what */
MPI_File_get_size(*in, &filesize);
localsize = filesize/size;
start = rank * localsize;
end = start + localsize - 1;
/* add overlap to the end of everyone's chunk... */
end += overlap;
/* except the last processor, of course */
if (rank == size-1) end = filesize;
localsize = end - start + 1;
/* allocate memory */
chunk = malloc( (localsize + 1)*sizeof(char));
/* everyone reads in their part */
MPI_File_read_at_all(*in, start, chunk, localsize, MPI_CHAR, MPI_STATUS_IGNORE);
chunk[localsize] = '\0';
/*
* everyone calculate what their start and end *really* are by going
* from the first newline after start to the first newline after the
* overlap region starts (eg, after end - overlap + 1)
*/
int locstart=0, locend=localsize;
if (rank != 0) {
while(chunk[locstart] != '\n') locstart++;
locstart++;
}
if (rank != size-1) {
locend-=overlap;
while(chunk[locend] != '\n') locend++;
}
localsize = locend-locstart+1;
/* Now let's copy our actual data over into a new array, with no overlaps */
char *data = (char *)malloc((localsize+1)*sizeof(char));
memcpy(data, &(chunk[locstart]), localsize);
data[localsize] = '\0';
free(chunk);
/* Now we'll count the number of lines */
*nlines = 0;
for (int i=0; i<localsize; i++)
if (data[i] == '\n') (*nlines)++;
/* Now the array lines will point into the data array at the start of each line */
/* assuming nlines > 1 */
*lines = (char **)malloc((*nlines)*sizeof(char *));
(*lines)[0] = strtok(data,"\n");
for (int i=1; i<(*nlines); i++)
(*lines)[i] = strtok(NULL, "\n");
return;
}
void processlines(char **lines, const int nlines, const int rank) {
for (int i=0; i<nlines; i++) {
float a, b;
sscanf(lines[i],"%f %f", &a, &b);
printf("%d: <%s>: %f + %f = %f\n", rank, lines[i], a, b, a+b);
}
}
int main(int argc, char **argv) {
MPI_File in;
int rank, size;
int ierr;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (argc != 2) {
if (rank == 0) fprintf(stderr, "Usage: %s infilename\n", argv[0]);
MPI_Finalize();
exit(1);
}
ierr = MPI_File_open(MPI_COMM_WORLD, argv[1], MPI_MODE_RDONLY, MPI_INFO_NULL, &in);
if (ierr) {
if (rank == 0) fprintf(stderr, "%s: Couldn't open file %s\n", argv[0], argv[1]);
MPI_Finalize();
exit(2);
}
const int overlap=100;
char **lines;
int nlines;
readlines(&in, rank, size, overlap, &lines, &nlines);
printf("Rank %d has %d lines\n", rank, nlines);
processlines(lines, nlines, rank);
free(lines[0]);
free(lines);
MPI_File_close(&in);
MPI_Finalize();
return 0;
}
そして、提供されたデータセットでこれを実行します。
$ mpirun -np 2 ./textio foo2.in
Rank 0 has 4 lines
0: <45.87 13.22>: 45.869999 + 13.220000 = 59.090000
0: <45.71 13.27>: 45.709999 + 13.270000 = 58.980000
0: <45.78 13.21>: 45.779999 + 13.210000 = 58.989998
0: <45.67 13.1>: 45.669998 + 13.100000 = 58.769997
Rank 1 has 3 lines
1: <45.7 13.24>: 45.700001 + 13.240000 = 58.940002
1: <45.81 13.28>: 45.810001 + 13.280000 = 59.090000
1: <45.85 13.32>: 45.849998 + 13.320000 = 59.169998