【发布时间】: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';