c - MPI 分散/发送数据到进程

标签 c mpi scatter

我正在使用 n = 2 运行我的代码。我一直在尝试研究,但我不明白为什么当我尝试多次运行我的代码时会获得不同的输出。 在下面,您可以看到当我使用 n = 2 运行时的输出,并且我的 txt.file 每行包含 73 个字符,由 4 行组成。

这是我第一次运行的输出,是预期和想要的输出 This is my output the first time and run and is the expected and wanted output

这是我第二次运行代码时的输出 This is the output the second time I run the code

这是我第三次运行代码的输出 This is the output the third time I run the code

我不知道如何防止图像 2 中发生错误(第二个打印行中有一个\274),但特别是在第三次运行代码时出现错误。我必须使用 MPI_Allocate 吗?我是否提前释放了矩阵?

这是我的代码:

#define MAXCHAR 73
#define MAXLENGTH 100

int main(int argc, char** argv) {
FILE *fp;
char* filename = "/Users/test.txt";
char *line = malloc(MAXCHAR);
char (*matA)[MAXCHAR] = NULL;
char str[MAXCHAR];
int rowCount, num_rows, i, my_id, 
root_process,num_procs,rows_per_process;

MPI_Init(&argc, &argv);
root_process = 0;



/* find out MY process ID, and how many processes were started. */
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);


// READ TXT FILE INTO DYNAMIC ARRAY
if(my_id == root_process){
    fp = fopen(filename, "r");
    if (fp == NULL){
        printf("Could not open file %s",filename);
        return 1;
    }
    //NUMBER OF lines
    size_t count=1000;
    rowCount=0;
    while(getline(&line, &count, fp)!=-1) {
        rowCount++;
    }
    //REWIND file
    rewind(fp);

    matA = malloc(rowCount*sizeof(matA));
    i = 0;
    while (fgets(str, MAXCHAR, fp) != NULL){
        for (size_t j = 0; j < MAXCHAR; j++) {
            if(str[j] == '\n'){
                continue;
            }
            matA[i][j] = str[j];
        }
        i++;
        num_rows = i;
    }
    fclose(fp);

}

// BCAST rowCount to Calculate rows each process will receive
MPI_Bcast(&rowCount, 1, MPI_INT, 0, MPI_COMM_WORLD);
rows_per_process = rowCount/num_procs;



char(*part_matrix)[MAXCHAR];
part_matrix = malloc(rows_per_process*sizeof(*part_matrix));


MPI_Scatter(&(matA[0][0]), rows_per_process*73, MPI_CHAR, &(part_matrix[0][0]), rows_per_process*73, MPI_CHAR, 0, MPI_COMM_WORLD);
printf("Process %i received %i rows:\n", my_id, rows_per_process);

// PRINTING
for (size_t i = 0; i < rows_per_process; i++) {
    printf("PROCESS %i PRINTS LINE NUMBER %zu:\n", my_id, i);
    for (size_t j = 0; j < MAXCHAR; j++) {
        printf("%c", part_matrix[i][j]);
    }
    printf("\n" );
}

free(part_matrix);
MPI_Finalize();
return 0;
}

最佳答案

我相信您的大部分问题都来自于以下事实:

char (*matA)[MAXCHAR] = NULL;
matA = malloc(rowCount*sizeof(matA));

这是一种奇怪的数据分配方式。

char *matA = NULL;
matA = malloc(rowCount*MAXCHAR*sizeof(char));

看起来更合理

同样的情况

char *part_matrix=NULL;
part_matrix = (char*) malloc(rows_per_process*MAXCHAR*sizeof(char));

这样,您就可以确保 matA 和 part_matrix 在内存中连续,并且在使用 MPI 函数时不会造成任何损害(内存方面)。

MPI_Scatter simply becomes MPI_Scatter(matA, rows_per_process*MAXCHAR, MPI_CHAR, part_matrix, rows_per_process*MAXCHAR, MPI_CHAR, 0, MPI_COMM_WORLD);

我改变了你阅读文件的方式,以便工作......

matA = (char*)malloc(rowCount*MAXCHAR*sizeof(char));
i = 0;
while (getline(&line, &count, fp)!=-1){
    for (j = 0; j < MAXCHAR; j++) {
        matA[i*MAXCHAR+j] = line[j];
    }
    i++;
    num_rows = i;
}

因此,您获得了完整的工作示例,其中 test.txt

AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA  
BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB  
CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC  
DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD  

主文件

#include <stdlib.h>
#include <stdio.h>
#include "mpi.h"
#define MAXCHAR 73
#define MAXLENGTH 100

int main(int argc, char** argv) {
FILE *fp;
char* filename = "test.txt";
char *line = (char*) malloc(MAXLENGTH);
char * matA= NULL;
char str[MAXCHAR];
int rowCount, num_rows, i, my_id, 
root_process,num_procs,rows_per_process, j;

MPI_Init(&argc, &argv);
root_process = 0;



/* find out MY process ID, and how many processes were started. */
MPI_Comm_rank(MPI_COMM_WORLD, &my_id);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);

// READ TXT FILE INTO DYNAMIC ARRAY
if(my_id == root_process){
    fp = fopen(filename, "r");
    if (fp == NULL){
        printf("Could not open file %s",filename);
        return 1;
    }
    //NUMBER OF lines
    size_t count=1000;
    rowCount=0;
    while(getline(&line, &count, fp)!=-1) {
        rowCount++;
    }
    //REWIND file
    rewind(fp);

    matA = (char*)malloc(rowCount*MAXCHAR*sizeof(char));
    i = 0;
    while (getline(&line, &count, fp)!=-1){
        for (j = 0; j < MAXCHAR; j++) {
            matA[i*MAXCHAR+j] = line[j];
        }
        i++;
        num_rows = i;
    }
    fclose(fp);
}

// BCAST rowCount to Calculate rows each process will receive
MPI_Bcast(&rowCount, 1, MPI_INT, 0, MPI_COMM_WORLD);
rows_per_process = rowCount/num_procs;


char *part_matrix = NULL;
part_matrix = (char*) malloc(rows_per_process*MAXCHAR*sizeof(char));


MPI_Scatter(matA, rows_per_process*MAXCHAR, MPI_CHAR, part_matrix, rows_per_process*MAXCHAR, MPI_CHAR, 0, MPI_COMM_WORLD);

if(my_id == root_process){
free(matA);
}

printf("Process %i received %i rows:\n", my_id, rows_per_process);
// PRINTING
for (i = 0; i < rows_per_process; i++) {
    printf("PROCESS %i PRINTS LINE NUMBER %zu:\n", my_id, i);
    for (j = 0; j < MAXCHAR; j++) {
        printf("%c", part_matrix[i*MAXCHAR+j]);
    }
    printf("\n" );
}

free(part_matrix);
MPI_Finalize();
return 0;
}

mpirun -n 4 返回

PROCESS 0 PRINTS LINE NUMBER 0:
AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA
Process 1 received 1 rows:
PROCESS 1 PRINTS LINE NUMBER 0:
BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
Process 2 received 1 rows:
PROCESS 2 PRINTS LINE NUMBER 0:
CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC
Process 3 received 1 rows:
PROCESS 3 PRINTS LINE NUMBER 0:
DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD

mpirun -n 2 返回

Process 0 received 2 rows:
PROCESS 0 PRINTS LINE NUMBER 0:
AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA AAAAAAAA
PROCESS 0 PRINTS LINE NUMBER 1:
BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB BBBBBBBB
Process 1 received 2 rows:
PROCESS 1 PRINTS LINE NUMBER 0:
CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCC
PROCESS 1 PRINTS LINE NUMBER 1:
DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDDDD

关于c - MPI 分散/发送数据到进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52981783/

相关文章:

c - 如何在 C 中返回 long 的结束数字(特别是当它们为 0 时)

c++ - MPI_Scatter 段错误

python - `map.scatter` basemap 不显示标记

c - C中的低级打印

c - OSX 上的 getsockopt 返回错误值?

file-io - 如何用 MPI_File_open 替换 MPI 中的现有文件

c - MPI 将矩阵划分为 block

字典中的 Matplotlib 散点图标记类型

c - getchar_unlocked() 解释

R 在 HPC MPIcluster 上运行 foreach dopar 循环