Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 英特尔TBB并行_reduce返回错误结果_C++_Parallel Processing_Intel_Tbb - Fatal编程技术网

C++ 英特尔TBB并行_reduce返回错误结果

C++ 英特尔TBB并行_reduce返回错误结果,c++,parallel-processing,intel,tbb,C++,Parallel Processing,Intel,Tbb,我正在尝试使用Intel TBB parallel_reduce计算Connect 4游戏中对用户移动的最佳响应。我编写了一个简单的函数,当传递一个列数时,返回一个启发式分数,该分数对应于执行该动作的效用。我的目的是并行调用这个函数,然后返回返回结果的缩减。减少将是启发式得分最高的动作 然而,我发现我得到的结果不一致。我希望列0的移动可以从并行reduce返回(因为我已经编写了启发式评分函数,它返回7列数字作为评分) 我附上了C++代码。以下是它生成的示例输出: 返回移动0 返回移动1 回击动作

我正在尝试使用Intel TBB parallel_reduce计算Connect 4游戏中对用户移动的最佳响应。我编写了一个简单的函数,当传递一个列数时,返回一个启发式分数,该分数对应于执行该动作的效用。我的目的是并行调用这个函数,然后返回返回结果的缩减。减少将是启发式得分最高的动作

然而,我发现我得到的结果不一致。我希望列0的移动可以从并行reduce返回(因为我已经编写了启发式评分函数,它返回7列数字作为评分)

<>我附上了C++代码。以下是它生成的示例输出:

返回移动0

返回移动1

回击动作2

回击动作6

回击动作4

回击动作5

比较移动5返回移动3和6

比较动作3和4

比较动作3和5

比较动作2和3

最好的动作是2

我已经看过代码很多次了,我不明白为什么它不总是返回0作为最佳移动。它有时确实返回零,但并不总是。正如您在上面看到的,move 0是经过计算的,但是reduce lambda函数从未将其作为输入。任何帮助都将不胜感激。我模糊地怀疑我使用的0的标识可能不正确。但是我不确定它应该是什么

#include <tbb\blocked_range.h>
#include <tbb\parallel_reduce.h>

#include <iostream>
#include <vector>

int getMoveHueristicScore(int columnCounter) {

    int returnValue = 7 - columnCounter;
    return returnValue;
}

int bestHeuristicScore(int numberOfColumns) {

    std::vector<int> moveScores(numberOfColumns, -1 * INT_MAX);

    return tbb::parallel_reduce(
        tbb::blocked_range<int>(0, numberOfColumns),
        0,
        [=, &moveScores](const tbb::blocked_range<int>& range, int bestMove)->int {
        int bestScore = -1 * INT_MAX;
        for (int columnCounter = range.begin(); columnCounter != range.end(); ++columnCounter) {
            moveScores.at(columnCounter) = getMoveHueristicScore(columnCounter);
            if (moveScores.at(columnCounter) > bestScore) {
                bestScore = moveScores.at(columnCounter);
                bestMove = columnCounter;
            }
        }
        std::cout << "Return move " << bestMove << std::endl;
        return bestMove;
    },
        [=, &moveScores](int bestMove1, int bestMove2)->int {
        std::cout << "Compare moves " << bestMove1 << " & " << bestMove2 << std::endl;
        if (moveScores.at(bestMove1) > moveScores.at(bestMove2)) {
            return bestMove1;
        }
        else {
            return bestMove2;
        }
    }
    );
}

int main() {

    int bestMove = bestHeuristicScore(7);
    std::cout << "Best move is " << bestMove << std::endl;
    return 0;
}
#包括
#包括
#包括
#包括
int getMoveHueristicScore(int列计数器){
int returnValue=7-列计数器;
返回值;
}
int bestHeuristicScore(int numberOfColumns){
std::向量移动分数(numberOfColumns,-1*INT_MAX);
返回tbb::并行减少(
tbb::阻塞的_范围(0,numberOfColumns),
0,
[=,&moveScores](常量tbb::阻塞的范围和范围,int-bestMove)->int{
int bestScore=-1*int_MAX;
对于(int columnCounter=range.begin();columnCounter!=range.end();++columnCounter){
moveScores.at(columnCounter)=getMoveHueristicScore(columnCounter);
if(moveScores.at(columnCounter)>最佳分数){
bestScore=moveScores.at(列计数器);
bestMove=列计数器;
}
}

std::cout您声称缩减的左侧标识为
0
,但事实显然并非如此。您必须提供此类标识,并在缩减器中处理它。请尝试
-1
并显式处理它

并且
-INT_MAX
关闭1

当您遇到bug时,请明确捕获(删除
=


我很惊讶您的示例输出在减少时没有提到
1
,但我对缺少
0
并不惊讶您正在从多个线程访问
std::vector
,这是不安全的。这可能是问题的根源。将
moveScores
容器更改为
tbb::concurrent\vect或者

在这种情况下,
tbb::parallel_reduce
没有问题。问题是您的代码忽略了
func
函数的
init
参数

TBB对如何执行缩减有不同的选项。它可以选择为不同线程中的不同子范围调用
func
,然后使用
reduce
函数组合结果;它可以在同一线程中多次调用
func
,每次都传递上一次调用的结果;或者它可以同时使用这两种策略

查看
func
的实现:

[=, &moveScores](const tbb::blocked_range<int>& range, int bestMove)->int {
    int bestScore = -1 * INT_MAX;
    for (int columnCounter = range.begin(); columnCounter != range.end(); ++columnCounter) {
        moveScores.at(columnCounter) = getMoveHueristicScore(columnCounter);
        if (moveScores.at(columnCounter) > bestScore) {
            bestScore = moveScores.at(columnCounter);
            bestMove = columnCounter;
        }
    }
    std::cout << "Return move " << bestMove << std::endl;
    return bestMove;
}

然后TBB将从一次调用
func
到下一次调用,携带运行中的最佳分数,确保最终结果确实是全局最佳分数。

谢谢@Yakk。我用-1*INT_MAX解决了这个问题,改为用-1填充向量。我将标识改为-1,并更新了reducer,以便在ny参数为-1。我还删除了“=”明确捕获。但这没有帮助。我仍然得到不一致的结果。返回移动0返回移动1返回移动2返回移动6返回移动4返回移动3比较移动3和4返回移动5比较移动5和6比较移动3和5比较移动2和3最佳移动是2@AggieMan所以,我在谷歌上搜索了tbb parallel_reduce bu几年前,一些错误(挂起、清理失败等)让人不安。也许代码…只是错误?有两个重载,另一个看起来更老(因为它早于lambda),可能尝试使用较旧的版本可能会得到较少的bug?谢谢@Yakk。这很不幸。也许英特尔很快就会解决这个问题。我有一个解决方法,可以减少映射并使用映射(针对)然后是一个for循环来完成Reduce部分。这是有效的。我将尝试另一个parallel\u for,看看它是否有效。
parallel\u Reduce
(在本例中)中没有错误-请参阅。每个线程都将获得向量索引的独立范围。因此,这应该不是问题。向量不会调整大小,否则会导致问题。我将尝试使用并发向量看看是否有帮助。谢谢!!!我尝试了并发向量,但得到了与std::vector相同的结果。没有时间进行检查。将进行检查本周。与其他东西有关。我尝试了这个,结果它崩溃了。仔细看,我不确定这个解释对我是否有意义。建议的更改是并行reduce的Map部分。我的印象是,所有Map部分的输出都被赋予reduce函数(第二个lambda)而不是运行映射部件的另一个线程。可能我对TBB的理解是错误的。我不确定现在该怎么办。
func
不是真正的映射,它是一个子范围的缩减
int bestScore = moveScores.at(bestMove);