本文介绍了使用MPI_Gather openmpi c收集字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为每个进程生成一个字符串,然后收集所有内容.但是在每个进程中创建的字符串都是通过附加int和chars来创建的.

I want to generate an string with each process and then gather everything. But the strings created in each process are created by appending ints and chars.

我仍然无法正确收集所有内容.我可以一张一张地打印所有部分字符串,但是如果尝试打印rcv_string,我只会得到一个部分字符串,或者可能是分段错误.

I'm still not able to gather everything correctly. I can print all the partial strings one by one, but If I try to print the rcv_string, I only get one partial string or maybe a Segmentation Fault.

我尝试使用memset在字符串的末尾放置零,以动态和静态方式为字符串保留内存,但是我找不到办法.

I've tried putting zeros at the end of strings with memset, reserving memory for the strings dynamically and statically, ... But I don't find the way.

如果有人知道如何使琴弦弹弦并正确地进行收集以达到目标,那将是很好的.

It would be great if someone knew how to inizialize the strings and do the gather properly for achieving the objective.

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;
}

推荐答案

我设法重现了仅打印一个部分字符串的错误行为.

I managed to reproduce the incorrect behavior where only one partial string is printed.

这与您使用sprintf有关.

C如何处理char数组?

在C语言中使用数组时,必须首先为其分配内存.动态的还是静态的,都没有关系.假设您为10个char s分配了足够的内存.

When working with arrays in C, you must first allocate memory for it. Dynamic or static, it doesn't matter. Suppose you allocate enough memory for 10 chars.

char my_string[10];

如果不进行初始化,则其中包含无用的字符.

Without initializing it, it contains nonsense characters.

让我们假装my_string包含"qwertyuiop".

假设您要用字符串foo填充my_string.您使用sprintf.

Suppose you want to fill my_string with the string foo. You use sprintf.

sprintf(my_string, "foo");

C如何用3个字符填充10个插槽?

How does C fill 10 slots with 3 characters?

它用3个字符填充前3个插槽.然后,它用字符串结尾"字符填充第四个插槽.这用'\0'表示,在通过编译器时会转换为字符串结尾"字符.

It fills the first 3 slots with the 3 characters. Then, it fills the 4th slot with an "end of string" character. This is denoted by '\0', which is converted to an "end of string" character when it goes through the compiler.

因此,在您执行命令后,my_string包含"foo\0tyuiop".如果打印出my_string,则C知道不打印出\0之后的废话字符.

So, after your command, my_string contains "foo\0tyuiop". If you print out my_string, C knows not to print out the nonsense characters after the \0.

这与MPI_Gather有何关系?

How does this relate to MPI_Gather?

MPI_Gather收集来自不同进程的数组,并将它们全部放入一个进程的一个数组中.

MPI_Gather collects arrays from different processes, and puts them all into one array on one process.

如果在进程0上具有"foo\0tyuiop",在进程1上具有"bar\0ghjkl;",则它们将合并为"foo\0tyuiopbar\0ghjkl;".

If you had "foo\0tyuiop" on process 0 and "bar\0ghjkl;" on process 1, they get combined into "foo\0tyuiopbar\0ghjkl;".

如您所见,进程1的数组出现在进程0的行尾"字符之后.C会将进程1的所有字符都当作废话.

As you can see, the array from process 1 appears after the "end of line" character from process 0. C will treat all of the characters from process 1 as nonsense.

补丁解决方案

不要立即尝试打印所有的rcv_string,而是要确认到整个字符串中都有字符串结尾"字符.然后,根据其产生的过程,打印出具有不同字符串开始"位置的字符串.

Rather than attempting to print all of rcv_string at once, acknowledge that there are "end of string" characters scattered throughout. Then, print out strings with different "start of string" positions, according to the process it came from.

#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;
}

这篇关于使用MPI_Gather openmpi c收集字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 00:24