我有以下模板化函数,它在 GameTime (size_t) 的集合上采用 GameName (std::string) 和一对开始/结束迭代器。它遍历范围并将 GameTime-s 加在一起,并返回游戏名称、总游戏时间和平均游戏时间 (GameStats) 的元组:
template<typename InputIt>
GameStats calculateGameStats(const GameName& _gameName, const InputIt _begin, const InputIt _end)
{
std::string logMessage = "Started process for game " + _gameName + ":[ ";
for_each(_begin,_end,[&logMessage](GameTime e){ logMessage += std::to_string(e) + ',';});
std::clog << logMessage + " ]\n";
size_t itemCount = 0;
GameTime gameTime =
std::accumulate(_begin,_end,0,[&itemCount](const GameTime _lhs, const GameTime _rhs)
{
++itemCount;
return _lhs + _rhs;
});
logMessage = "Ended process for game " + _gameName + ":[ ";
for_each(_begin,_end,[&logMessage](GameTime e){ logMessage += std::to_string(e) + ',';});
std::clog << logMessage + " ]\n";
return std::make_tuple(_gameName, gameTime, gameTime / itemCount);
}
(出于调试目的,我还列出了我们在开始和结束时迭代的元素。显然它们每次都应该相同,但见下文。)
引用 std::vector 的此函数的类似版本工作正常,但是当它的多个实例并行运行时,这个新函数似乎弄乱了它的迭代器。下面是为每个游戏启动一个进程的代码:
// Start processing each game's stats in parallel
std::vector< std::future<GameStats> > processVector;
processVector.reserve(gameCount);
for(const std::pair<GameName, std::vector<GameTime> >& entryListPair : gameEntries)
{
const std::string& gameName = entryListPair.first;
const std::vector<GameTime>& entryList = entryListPair.second;
processVector.push_back(std::async(std::launch::async,
&calculateGameStats<decltype(entryList.cbegin())>,
gameName,
entryList.cbegin(),
entryList.cend()));
assert((processVector.cend()-1)->valid());
}
(GameEntries 是将 GameName 映射到 GameTime 向量的 std::map 类型)
以下是运行程序输出的相关部分:
Started process for game CoD:[ 182,1264, ]
Ended process for game CoD:[ 606,1667, ]
Started process for game DotA:[ 606,1667, ]
Ended process for game DotA:[ 606,1667, ]
Started process for game GTAV:[ 606, ]
Ended process for game GTAV:[ 606, ]
Started process for game HotS:[ 606, ]
Ended process for game HotS:[ 606, ]
Started process for game LoL:[ 1277,193, ]
Ended process for game LoL:[ 1277,193, ]
Started process for game MC:[ 857,193, ]
Ended process for game MC:[ 857,193, ]
Started process for game OW:[ 0, ]
Note: 7 games in map, created 7 processes.
Ended process for game OW:[ 140377361861512, ]
Writing entry: CoD 2273 1136
Writing entry: DotA 2273 1136
Writing entry: GTAV 606 606
Writing entry: HotS 606 606
Writing entry: LoL 1470 735
Writing entry: MC 1050 525
Writing entry: OW 650759048 650759048
After processing: CoD:[ 1354,1442,]
After processing: DotA:[ 2137,1264,]
After processing: GTAV:[ 182,]
After processing: HotS:[ 2551,]
After processing: LoL:[ 606,1667,]
After processing: MC:[ 1277,193,]
After processing: OW:[ 857,]
Done!
多次运行该程序会产生不同的结果,从某些游戏的正确结果到到处都是完全错误的数字。在程序完成后,我还会列出每个游戏的所有 GameTime 条目,以确保它没有被修改,以防万一这就是问题所在,但向量都毫发无损地从中出来。
然而,从输出中可以看出,在同一个函数中从(假定为常数和未修改的)开始到结束迭代每次都会产生不同的结果。仅当任务并行运行时才会出现这种情况。如果按顺序运行(通过在启动下一个未来之前在每个未来上调用 wait() ),程序运行正确,所以我的猜测是每个线程由于某种原因使其他的迭代器无效,即使它们是不同向量的输入迭代器,它们都是按值传递的。
我想知道是什么导致了这种干扰,以及如何让它们并行工作。