gpt4 book ai didi

c++ - MPI收集字符串数组

转载 作者:行者123 更新时间:2023-12-02 10:03:23 25 4
gpt4 key购买 nike

我正在尝试将词典集合合并到根进程中。这是一个简短的示例:

#define MAX_CF_LENGTH 55

map<string, int> dict;

if (rank == 0)
{
dict = {
{"Accelerator Defective", 33},
{"Aggressive Driving/Road Rage", 27},
{"Alcohol Involvement", 19},
{"Animals Action", 30}};
}
if (rank == 1)
{
dict = {
{"Driver Inexperience", 6},
{"Driverless/Runaway Vehicle", 46},
{"Drugs (Illegal)", 38},
{"Failure to Keep Right", 24}};
}
if (rank == 2)
{
dict = {
{"Lost Consciousness", 1},
{"Obstruction/Debris", 8},
{"Other Electronic Device", 25},
{"Other Lighting Defects", 43},
{"Other Vehicular", 7}};
}

Scatterer scatterer(rank, MPI_COMM_WORLD, num_workers);
scatterer.gatherDictionary(dict, MAX_CF_LENGTH);
gatherDictionary()内的想法是在每个进程中将每个键放在 char数组中(允许重复)。之后,将所有键收集到根中并创建最终(合并的)字典,然后广播它。这是代码:

void Scatterer::gatherDictionary(map<string,int> &dict, int maxKeyLength)
{
// Calculate destination dictionary size
int numKeys = dict.size();
int totalLength = numKeys * maxKeyLength;
int finalNumKeys = 0;
MPI_Reduce(&numKeys, &finalNumKeys, 1, MPI_INT, MPI_SUM, 0, comm);

// Computing number of elements that are received from each process
int *recvcounts = NULL;
if (rank == 0)
recvcounts = new int[num_workers];

MPI_Gather(&totalLength, 1, MPI_INT, recvcounts, 1, MPI_INT, 0, comm);

// Computing displacement relative to recvbuf at which to place the incoming data from each process
int *displs = NULL;
if (rank == 0)
{
displs = new int[num_workers];

displs[0] = 0;
for (int i = 1; i < num_workers; i++)
displs[i] = displs[i - 1] + recvcounts[i - 1] + 1;
}

char(*dictKeys)[maxKeyLength];
char(*finalDictKeys)[maxKeyLength];
dictKeys = (char(*)[maxKeyLength])malloc(numKeys * sizeof(*dictKeys));
if (rank == 0)
finalDictKeys = (char(*)[maxKeyLength])malloc(finalNumKeys * sizeof(*finalDictKeys));

// Collect keys for each process
int i = 0;
for (auto pair : dict)
{
strncpy(dictKeys[i], pair.first.c_str(), maxKeyLength);
i++;
}

MPI_Gatherv(dictKeys, totalLength, MPI_CHAR, finalDictKeys, recvcounts, displs, MPI_CHAR, 0, comm);

// Create new dictionary and distribute it to all processes
dict.clear();
if (rank == 0)
{
for (int i = 0; i < finalNumKeys; i++)
dict[finalDictKeys[i]] = dict.size();
}

delete[] dictKeys;
if (rank == 0)
{
delete[] finalDictKeys;
delete[] recvcounts;
delete[] displs;
}

broadcastDictionary(dict, maxKeyLength);
}

我已经测试过 broadcastDicitonary()的正确性,因此可以确定。调试到收集功能中,我得到以下部分结果:
Recvcounts:
220
220
275

Displacements:
0
221
442

FinalDictKeys:
Rank:0 Accelerator Defective
Rank:0 Aggressive Driving/Road Rage
Rank:0 Alcohol Involvement
Rank:0 Animals Action
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0
Rank:0

由于只收集根数据,所以我想知道这是否与字符分配有关,即使它应该是连续的也是如此。我不认为这与结尾缺少空字符有关,因为每个字符串/键已经有很多填充。
在此先感谢您指出任何缺失或改进之处,如果您需要任何其他信息,请发表评论。

如果您想自己进行测试,我只将代码放到一个文件中,就可以编译和运行了(当然,这适用于3个mpi进程)。 Code Here

最佳答案

displs[i] = displs[i - 1] + recvcounts[i - 1] + 1;

最后的 + 1是多余的。更改为:
displs[i] = displs[i - 1] + recvcounts[i - 1];

关于c++ - MPI收集字符串数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61438865/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com