【问题标题】:MPI gives strange character in process 0 when using strcat使用 strcat 时,MPI 在进程 0 中给出奇怪的字符
【发布时间】:2020-05-04 06:51:55
【问题描述】:

我正在做一个项目,以找出每个项目在 5 组中彼此相遇的频率。默认项目是 10,使用命令 mpirun -n 10 ./a.out 给出了正确的结果,除了进程 0 中的结果。 当我使用strcat追加字符串时,只有进程0在代码末尾添加了奇怪的字符'4'。 结果在这里: screenshot

问题出在代码中:

if(indexListofEachItem[rank][j] == indexListofEachItem[i+1][k])
            {
                char ctemp[1];
                ctemp[0] = indexListofEachItem[i+1][k];
                strcat(frequence[n], ctemp); 
                count[n]++;
            }

以下是完整代码:

#include <stdio.h> 
#include <mpi.h> 
#include <stdlib.h> 
#include <time.h> 
#include <string.h> 
#include <stdbool.h>
int main(int argc, char *argv[]) {
int gen_val,first_val, second_val, temp, rank,proc_size;
int allItem = 0;
int n = 0;
int listofAllItem[50];
char indexListofEachItem[50][50];
bool found = false;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &proc_size);
int numbOfItem = 5 ;
int val[5][5] ={5,4,6,7,8,
                5,0,4,9,8,
                1,6,2,3,9,
                3,7,1,0,5,
                4,9,8,0,2};
int count[10] = {0,0,0,0,0,0,0,0,0,0};
int firstNum[50];
int secondNum[50];
char frequence[9][50] = {0};
int allListItem[5];
int index;int outofrangeVal = 10;
for(int i= 0; i< 5;i++)
{
    if(rank == i)
    {
        int j = 0;
        int min = 0;
        int count = 0;
        for(int ii = 0 ; ii < numbOfItem ; ii++)
            storedVal[ii] = outofrangeVal;
        printf("process %d: %d, %d, %d, %d, %d\n",rank, val[rank][0], val[rank][1], val[rank][2],val[rank][3], val[rank][4]);
        if(rank != 0)
            MPI_Send(val[rank], 5, MPI_INT, 0, 0, MPI_COMM_WORLD);
    }
    MPI_Barrier(MPI_COMM_WORLD);
}
if(rank == 0)
{
    index = 0;
    for(int i = 0; i < 5; i++)
    {
        listofAllItem[i] = val[0][i];
        sprintf(indexListofEachItem[i],"%d", index);
        allItem++;
    }
    for(int i = 1; i < 5; i++)
    {
        MPI_Recv(allListItem, 5, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        index = i;
        char c[5];
        sprintf(c, "%d", i);
        for(int k = 0; k < 5; k++)
        {
            for(int j = 0; j < allItem; j++)
                if(allListItem[k] == listofAllItem[j])
                {
                    strcat(indexListofEachItem[j], c);
                    found = true;
                } 
            if(found == false)
            {
                listofAllItem[allItem] = allListItem[k];
                strcpy(indexListofEachItem[allItem], c);
                allItem++;
            }
            found = false;
        }
    }
    for(int i = 0; i < proc_size - 1; i++)
        for(int j = i+1; j< proc_size; j++)
        {
            if(listofAllItem[i] > listofAllItem[j])
            {
                int temp = listofAllItem[j];
                listofAllItem[j] = listofAllItem[i];
                listofAllItem[i] = temp;
                char ctemp[50];
                strcpy(ctemp, indexListofEachItem[j]);
                strcpy(indexListofEachItem[j],indexListofEachItem[i]);
                strcpy(indexListofEachItem[i],ctemp);
            }
        }
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Bcast(listofAllItem, 10, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(indexListofEachItem, 2500, MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Bcast(&allItem, 1, MPI_INT, 0, MPI_COMM_WORLD);

MPI_Barrier(MPI_COMM_WORLD);    
n = 0;
for(int r = 0 ; r < proc_size; r++)
if(r == rank)
{
for(int i = rank; i < proc_size-1; i++)
{
    firstNum[n] = listofAllItem[rank];
    secondNum[n] = listofAllItem[i+1];
    for(int j = 0 ; j < strlen(indexListofEachItem[rank]); j++)
    {

        for(int k = 0; k < strlen(indexListofEachItem[i+1]); k++)
        {
            if(indexListofEachItem[rank][j] == indexListofEachItem[i+1][k])
            {
                char ctemp[1];
                ctemp[0] = indexListofEachItem[i+1][k];
                strcat(frequence[n], ctemp);
                count[n]++;
            }
        }

    }
    n++;
}
}
MPI_Barrier(MPI_COMM_WORLD);  

n = sizeof(secondNum)/sizeof(secondNum[0]);
int i = 0;
if(rank != proc_size-1)
do
{
    printf("rank %d, %d and %d appear %d times in index %s", rank, firstNum[i],secondNum[i],count[i], frequence[i]);
    printf("\n");
    i++;
}while(i< n && secondNum[i]!= 0);
printf("\n");
MPI_Barrier(MPI_COMM_WORLD);    

MPI_Finalize();
return 0;

}

【问题讨论】:

  • 生成的字符串有多长,是否溢出定义? Strcat 使用起来很危险,应该避免使用。
  • 以后所有的字符串都会被扩展,所以我只声明它们为50个元素。除了这个,我没有看到任何附加字符串功能。
  • 这是什么标准库/操作系统/编译器?你通常应该有strncat。如果您要动态分配/扩展字符串,则不应静态声明它们。
  • 我是在linux环境下编译的。对于 strncat,如何仅将源字符串中的 1 个字符附加到目标字符串?我在升级代码之前做静态测试我的算法
  • 哦,另一件事,你不能在 char[1] 后面加上缺少的 \0,如果它总是 1 个字符,你可以使用 strncat(frequence[n], demo, 1)char ctemp[2]; ctemp[1] = '\0';

标签: character mpi strcat


【解决方案1】:

您需要确保附加 \0 终止的字符串,仅:

    char ctemp[2];
    ctemp[1] = ’\0';
    ctemp[0] = indexListofEachItem[i+1][k];
    //if (strlen(frequence[n]) > 48) abort 
    strncat(frequence[n], ctemp, 2);

【讨论】:

  • 顺便说一句,如果这应该是高速成本,不使用字符串功能可能会更好(strcat 需要迭代整个现有字符串)。如果它总是使用frequence[n][++count[n]](加上memset)的单个字符可能会更好)
  • 在这种情况下,不要忘记在最后以空终止 frequence
猜你喜欢
  • 2010-12-23
  • 1970-01-01
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
  • 2016-01-11
  • 1970-01-01
  • 2018-06-27
相关资源
最近更新 更多