C++ openmp缩减的奇怪结果

C++ openmp缩减的奇怪结果,c++,parallel-processing,openmp,C++,Parallel Processing,Openmp,在本课程中: template <typename C, typename R, typename D> class myClass{ public: R Query(const C &query); ... private: struct Compare{ D val; size_t index; }; #pragma omp declare reduction(minimum : Co

在本课程中:

template <typename C, typename R, typename D>
class myClass{
    public:
    R Query(const C &query);
    ...
    private:
    struct Compare{
        D val;
        size_t index;
    };
    #pragma omp declare reduction(minimum : Compare : omp_out = omp_in.val < omp_out.val ? omp_in : omp_out)
    std::vector<C> values;
    ...
}


template <typename C, typename R, typename D>
R Cache<C,R,D>::Query(const C &query){
    Compare min;
    R result;
    if(!values.empty()){
            #pragma omp parallel for reduction(minimum:min)
            for(size_t i=1; i<values.size(); i++){
                D d = distance->compute(query, values[i]);
                std::cout<<" distance("<<query<<" "<<values[i].code<<")= "<<d;
                if(d < min.val){
                    std::cout<<" NEW MIN!";
                    min.val = d;
                    min.index = i;
                }
                std::cout<<std::endl;
            }
        std::cout<<"min.val="<<min.val<<std::endl;
   }
...
D=距离->计算查询,值[i];值是正确的,下面的打印也是正确的

然而,出于某种奇怪的原因,每次计算的平行度为min.val时,最后一次打印的结果总是min.val=0


显然,这不是全部代码,我尽可能地简化了它。

如果在并行块内初始化结构,则根本不需要初始化器

 #pragma omp declare reduction( \
    minimum : Compare : omp_out = omp_in.val < omp_out.val ? omp_in : omp_out\
    ) 

#pragma omp parallel reduction(minimum:min)
{
    D d = distance->compute(query, values[0]);
    min = Compare{d,0}
    #pragma omp for
    for(size_t i=1; i<values.size(); i++){
        d = distance->compute(query, values[i]);
        if(d < min.val)
            min = Compare{d,i};
    }
}

您缺少用户声明的缩减的初始化器:

#pragma omp declare reduction(minimum : Compare : omp_out = omp_in.val < omp_out.val ? omp_in : omp_out) \
                initializer (omp_priv=Compare{std::numeric_limits<D>::max(), -1})
或者,您可以添加成员初始化:

template <typename D>
class Foo {
struct Compare{
    D val {std::numeric_limits<D>::max()};
    int index {-1};
};

这是更一般的,即使没有-fopenmp,也能确保程序正常工作。

它的拼写是reductionmin:min.val,您至少需要lastprovatemin.index和一些min.val初始化。这里的其他人坚持用户定义的缩减。没有编译器警告吗?请学习如何进行正确的编译。这将大大改进您的问题。谢谢您的回答。但是,`error:expected end of line before'['token`,为什么?您使用的是哪种编译器?如果您的编译器不支持初始值设定项,您可以尝试第二种解决方案,而不使用reduce声明中的初始值设定项1。绝对需要对并行部分进行比较,2[]在标准中,只是标准中的syntrax提示,表明初始值设定项子句是可选的。3 RAND_MAX是一个糟糕的选择。@Zulan Tha问题是为什么初始代码会产生奇怪的结果。1是的,需要进行比较,如果没有它,代码将变成连续的,尽管与问题无关。2是的,初始化r是可选的,并且没有回答为什么他的编译器会出现错误的问题。3这是一个示例代码。您可以根据需要初始化任何内容。同样,所有这些注释与question@Zulan我试过我的答案,它是有效的。我真的不明白你指出了什么错误。我看到的是你把我的答案标为not有用,用不同的初始化重新发布相同的答案。因此,如果你不相信我,请尝试一下。无论如何,我只是想帮助一个家伙,你显然想提高你的声誉。即使初始化对你来说是一个问题,你也可以用一个很好的建设性评论指出。他还需要指定min=Compare{value,index}。在他的for循环中,他更改了成员变量,并在结构上声明了缩减。@Kochoba原始循环体是正确的。无需创建/分配新结构。修改成员就足够了。