我想使用Messgae Passing Interface(MPI)将一个字符串数组从主线程发送到从线程。即String[]str=新String[10]str[0]="XXX"。。。etc
如何做到这一点,同时避免将此数组中的每个元素作为一个字符链发送?
我成功地在一次发送操作中发送了一个整数数组。。。但当涉及字符串数组
发送字符串数组,尤其是在大小不同的情况下,是一个非常复杂的过程。有几种选择,但对MPI最友好的是使用MPI的打包和拆包功能,在mpiJava中公开为Comm.Pack
、Comm.Unpack
和Comm.Pack_size
。
你可以做一些类似的事情:
发件人
byte[][] bytes = new byte[nStr][];
int[] lengths = new int[nStr];
int bufLen = MPI.COMM_WORLD.Pack_size(1, MPI.INT);
bufLen += MPI.COMM_WORLD.Pack_size(nStr, MPI.INT);
for (int i = 0; i < nStr; i++) {
bytes[i] = str[i].getBytes(Charset.forName("UTF-8"));
lengths[i] = bytes[i].length;
bufLen += MPI.COMM_WORLD.Pack_size(lengths[i], MPI.BYTE);
}
byte[] buf = new byte[bufLen];
int position = 0;
int nStrArray[] = new int[1];
nStrArray[0] = nStr;
position = MPI.COMM_WORLD.Pack(nStrArray, 0, 1, MPI.INT,
buf, position);
position = MPI.COMM_WORLD.Pack(lengths, 0, nStr, MPI.INT,
buf, position);
for (int i = 0; i < nStr; i++) {
position = MPI.COMM_WORLD.Pack(bytes[i], 0, lengths[i], MPI.BYTE,
buf, position);
}
MPI.COMM_WORLD.Send(buf, 0, bufLen, MPI.PACKED, rank, 0);
将字符串长度放在辅助数组中,并将其打包在消息的开头,简化了接收器逻辑。
接收器
假设发件人排名为0。
Status status = MPI.COMM_WORLD.Probe(0, 0);
int bufLen = status.Get_count(MPI.PACKED);
byte[] buf = new byte[bufLen];
MPI.COMM_WORLD.Recv(buf, 0, bufLen, MPI.PACKED, status.source, status.tag);
int position = 0;
int nStrArray[] = new int[1];
position = MPI.COMM_WORLD.Unpack(buf, position,
nStrArray, 0, 1, MPI.INT);
int nStr = nStrArray[0];
int lengths[] = new int[nStr];
position = MPI.COMM_WORLD.Unpack(buf, position,
lengths, 0, nStr, MPI.INT);
String[] str = new String[nStr];
for (int i = 0; i < nStr; i++) {
byte[] bytes = new byte[lengths[i]];
position = MPI.COMM_WORLD.Unpack(buf, position,
bytes, 0, lengths[i], MPI.BYTE);
str[i] = new String(bytes, "UTF-8");
}
免责声明:我没有安装MPJ Express,我的Java知识非常有限。该代码基于mpiJava规范、MPJ Express JavaDocs以及互联网上的一些示例。
我不懂Java,但我会给你C的答案。然而,这些概念——尤其是解决这一问题的两种方法——在任何语言中都是相同的。
想象一下,如果这是一个简单的c字符串(有些字符以"\0"结尾)。有两种方法:
- 过度提供存储器并且接收高达某个限制
- 或者发送指示期望多少数据的消息
你有最长的长度吗?(例如PATH_MAX或类似的东西)。如果你不需要每一个字节的内存,你可以做
MPI_Send(str, strlen(str), MPI_CHAR, slave_rank, slave_tag, MPI_COMM_WORLD);
你可以把它和配对
MPI_Recv(str, MAX_LENGTH, MPI_CHAR, master_rank, slave_tag, MPI_COMM_WORLD);
如果你不喜欢最后有slop,你必须在两条消息中这样做:
len=strlen(str) + 1; /* +1 for the NULL byte */
MPI_Send(&len, 1, MPI_INT, slave_rank, slave_tag, MPI_COMM_WORLD);
MPI_Send(str, strlen(str), MPI_CHAR, slave_rank, slave_tag, MPI_COMM_WORLD);
你可以将其与相匹配
MPI_Recv(&len, 1, MPI_INT, master_rank, slave_tag, MPI_COMM_WORLD);
payload= malloc(len);
MPI_Recv(&payload, len, MPI_CHAR, master_rank, slave_tag, MPI_COMM_WORLD);