我想为每个进程生成一个字符串,然后收集所有内容。但是在每个进程中创建的字符串都是通过附加整数和字符来创建的。
我仍然无法正确收集所有内容。我可以逐个打印所有部分字符串,但是如果我尝试打印rcv_string,我只得到一个部分字符串或者可能是分段错误。
我尝试在memset的字符串末尾添加零,动态和静态地为字符串保留内存,但是我找不到方法。
如果有人知道如何对字符串进行初始化并正确地进行聚集以实现目标,那将会很棒。
int main(int argc, char *argv[]) {
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
char *string; // ????????????
char *rcv_string; // ????????????
if (rank == 0) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 1) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 2) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 3) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 4) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
else if (rank == 5) {
sprintf(string+strlen(string), "%dr%dg%db%dl\n",255,255,255,0);
}
MPI_Gather(string,???,MPI_CHAR,rcv_string,???,MPI_CHAR,0,MPI_COMM_WORLD);
if (rank == 0) {
printf("%s",rcv_string);
}
MPI_Finalize();
return 0;
}
答案 0 :(得分:1)
我设法重现了只打印一个部分字符串的错误行为。
这与您使用sprintf
。
C如何处理char
数组?
在C中使用数组时,必须先为其分配内存。动态或静态,无关紧要。假设您为10 char
s。
char my_string[10];
在不初始化的情况下,它包含无意义的字符。
让我们假装my_string
包含"qwertyuiop"
。
假设您要使用字符串my_string
填充foo
。您使用sprintf
。
sprintf(my_string, "foo");
C如何用3个字符填充10个插槽?
它用3个字符填充前3个插槽。然后,它用#34;字符串结尾填充第4个插槽"字符。这由'\0'
表示,它被转换为"字符串的结尾"通过编译器时的字符。
因此,在您的命令后,my_string
包含"foo\0tyuiop"
。如果您打印my_string
,C知道不会在\0
之后打印出无意义的字符。
这与MPI_Gather
有什么关系?
MPI_Gather
从不同进程收集数组,并将它们全部放在一个进程的一个数组中。
如果您在流程0上有"foo\0tyuiop"
而在流程1上有"bar\0ghjkl;"
,那么它们会合并到"foo\0tyuiopbar\0ghjkl;"
。
正如您所看到的,进程1中的数组出现在"行的末尾"来自进程0的字符.C会将进程1中的所有字符视为无意义。
一个不完整的解决方案
不是一次尝试打印所有rcv_string
,而是确认有#34;字符串结束"人物分散在各处。然后,打印出不同的"字符串的开头"职位,根据它来自的过程。
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
int part_str_len = 18;
char *my_string;
char *rcv_string;
if ((my_string = malloc(part_str_len*sizeof(char))) == NULL){
MPI_Abort(MPI_COMM_WORLD,1);
}
if ((rcv_string = malloc(part_str_len*size*sizeof(char))) == NULL){
MPI_Abort(MPI_COMM_WORLD,1);
}
sprintf(my_string, "%dr%dg%db%dl\n",255,255,255,0);
MPI_Gather(my_string,18,MPI_CHAR,rcv_string,18,MPI_CHAR,0,MPI_COMM_WORLD);
if (rank == 0) {
printf("%s",rcv_string);
}
char *cat_string;
if ((cat_string = malloc(part_str_len*size*sizeof(char))) == NULL){
MPI_Abort(MPI_COMM_WORLD,1);
}
if (rank == 0){
int i;
sprintf(cat_string, "%s", rcv_string);
for (i = 1; i < size; i++){
strcat(cat_string, &rcv_string[part_str_len*i]);
}
}
if (rank == 0) {
printf("%s",cat_string);
}
free(my_string);
free(rcv_string);
free(cat_string);
MPI_Finalize();
return 0;
}
答案 1 :(得分:-1)
尝试以下方法:
#define MAX_STR_LEN 100
int main(int argc, char *argv[]) {
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
char string[MAX_STR_LEN] = "some string";
char *rcv_string = NULL;
if (rank == 0) {
// Only the master needs to allocate the memory
// for the result string which needs to be large
// enough to contain the input strings from `size`
// peers.
rcv_string = malloc(MAX_STR_LEN * size);
}
...same code...
MPI_Gather(string, strlen(string), MPI_CHAR,
rcv_string, MAX_STR_LEN, MPI_CHAR, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("%s",rcv_string);
free(rcv_string);
}
MPI_Finalize();
return 0;
}
使用mpirun -n 5 ./a.out
运行此代码会产生以下结果:
some string255r255g255b0l
some string255r255g255b0l
some string255r255g255b0l
some string255r255g255b0l
some string255r255g255b0l
确保定义MAX_STR_LEN
,以便足以满足您的要求。如果值变大,您可能需要考虑堆分配(即malloc
)。