i有一个输入文件.txt,其中有序列:
NAMEOFSEQUENCE1/SEQUENCE1
NAMEOFSEQUENCE2/SEQUENCE2
NAMEOFSEQUENCE3/SEQUENCE3
我完成了一个结构:
typedef struct lane{
char *name;
char *sequence;
}lane;
并编写此代码:
int i=0;
lane* toSend = malloc(sizeof(*toSend)*3);
while (fgets(line,strlen(line),fileinput) != NULL){
//GETTING NAME AND SEQUENCE, LINE PER LINE
char *tempName = malloc(strlen(line)-strlen(strstr(line,"\"))+1);
strncpy(tempName,line,strlen(line)-strlen(strstr(line,"\")));
tempName[strlen(line)-strlen(strstr(line,"\"))] = ' ';
char *tempSequence = malloc(strlen(strstr(line,"\")));
strncpy(tempSequence,strstr(line,"\")+1,strlen(strstr(line,"\")));
tempSequence[strlen(strstr(line,"\"))-1] = ' ';
//FILLING TOSEND
toSend[i].name = malloc(strlen(line)-strlen(strstr(line,"\"))+1);
toSend[i].sequence = malloc(strlen(strstr(line,"\")));
howmuchbyte += strlen(line)+1;
strcpy(toSend[i].name,tempName);
strcpy(toSend[i].sequence,tempSequence);
i++;
}
我一次将文件的一行放入"行"变量,然后将每个序列的nameofsequencex放入tempname中,然后放入sequencex。
此时一切都在起作用。如果我打印" tosend"矢量,我将获得正确的价值!所以我写了这篇文章:
MPI_Send(toSend, 3, MPI_BYTE, 1, tag, MPI_COMM_WORLD);
因此,我从等级0的过程发送到等级1的进程(我有2个流程)。我将3个作为计数参数,因为我在数组中有3个元素。
等级1的过程要这样做:
lane* received = malloc(sizeof(*received)*3);
MPI_Recv(received, 3, MPI_BYTE, 0, tag, MPI_COMM_WORLD, &status);
如果我以等级1的方式进行此操作:
printf("%s",received[0].name);
我会得到一个分段故障。我错了?
如果您的字符串为固定最大长度,例如
,这可能会起作用。typedef struct lane{
char name[NAME_MAX];
char sequence[SEQ_MAX];
}lane;
在这种情况下,您可以简单地定义新的MPI结构化数据类型,并在发送和接收操作中使用它:
int blens[2] = { NAME_MAX, SEQ_MAX };
int disps[2] = { offsetof(lane, name), offsetof(lane, sequence) };
int oldtypes[2] = { MPI_CHAR, MPI_CHAR };
MPI_Datatype type_lane;
MPI_Type_create_struct(2, blens, disps, oldtypes, &type_lane);
MPI_Type_commit(&type_lane);
lane aLane[2];
if (rank == 0)
{
strncpy(aLane[0].name, NAME_MAX, "foo1");
strncpy(aLane[0].sequence, SEQ_MAX, "bar");
strncpy(aLane[1].name, NAME_MAX, "foo2");
strncpy(aLane[1].sequence, SEQ_MAX, "baz");
MPI_Send(aLane, 2, type_lane, 1, tag, MPI_COMM_WORLD);
}
else if (rank == 1)
{
MPI_Recv(aLane, 2, type_lane, 0, tag, MPI_COMM_WORLD, &status);
}
如果您的字符串的长度有很大变化,则在发送每个结构之前应序列化每个结构。我想到的最简单的事情就是将所有名称/序列对加入,由NUL隔开:
int total_length = 0;
for (i = 0; i < num_to_send; i++)
total_length += strlen(toSend[i].name) + strlen(toSend[i].sequence) + 2;
char *bigstr = malloc(total_length);
char *cur = bigstr;
for (i = 0; i < num_to_send; i++)
{
strcpy(cur, toSend[i].name);
cur += strlen(toSend[i].name) + 1;
strcpy(cur, toSend[i].sequence);
cur += strlen(toSend[i].sequence) + 1;
}
现在bigstr
的内容如下:
toSend[0].name toSend[0].sequence toSend[1].name toSend[1].sequence ....
发件人现在可以发送字符串并处置:
MPI_Send(bigstr, total_length, MPI_CHAR, 1, tag, MPI_COMM_WORLD);
接收器必须准备接收一条未知大小的消息。这可以通过首先致电MPI_Probe
,然后是MPI_Recv
:
MPI_Status;
MPI_Probe(1, tag, MPI_COMM_WORLD, &status);
MPI_Get_count(&status, MPI_CHAR, &total_length);
char *bigstr = malloc(total_length);
MPI_Recv(bigstr, total_length, MPI_CHAR, 1, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
现在是您必须将大字符串供电到一个元组集合的部分。一种方法是先走路并计算NUL的数量,然后将它们除以两个。然后再次行走并将每个项目复制到相应的位置:
int num_structs = 0;
for (i = 0; i < total_length; i++)
if (bigstr[i] == ' ') num_structs++;
num_structs /= 2;
lane *lanes = malloc(num_structs * sizeof(lane));
char *cur = bigstr;
for (i = 0; i < num_structs; i++)
{
lanes[i].name = strdup(cur);
cur += strlen(cur);
lanes[i].sequence = strdup(cur);
cur += strlen(cur);
}
另一个可能的解决方案是使用MPI_Pack
和MPI_Unpack
。
您不能仅通过MPI频道发送原始指针。好吧,您可以,但是从其他过程中接收指针的过程在记忆位置(在其自身的内存空间中)中没有相同的数据。
如果要通过MPI发送一个大小的数组(例如字符串),则需要先测试数组的大小,并在接收端分配适当尺寸的数组。
有关更多信息:如何使用MPI