You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为结构体中的std::vector声明OpenMP归约?

问题:OpenMP归约结构体中的std::vector报错

尝试通过OpenMP自定义归约声明对结构体中的std::vector执行求和归约,代码如下:

// g++ -fopenmp MRE.cpp -o MRE
#include <vector>
#include <algorithm>
#include <omp.h>

struct Particles {
    std::vector<double> fx;
};

#pragma omp declare reduction(vec_double_plus : std::vector<double> : \
std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus<double>()) \
) initializer(omp_priv = decltype(omp_orig)(omp_orig.size()))

int main() {
    Particles particles;
    
    // Initialize fx vector with 100 elements
    for (int i = 0; i < 100; ++i){
        particles.fx.push_back(0.0);
    }

    // Parallel region to set the values of fx
    #pragma omp parallel
    {
        // Thread-private local vector
        std::vector<double> thread_fx(particles.fx.size(), 0.0);

        #pragma omp for
        for (size_t i = 0; i < particles.fx.size(); ++i){
            thread_fx[i] = 1.0;  // Assign values to thread_fx
        }

        // Now we reduce thread_fx into particles.fx
        #pragma omp for reduction(vec_double_plus: particles.fx)
        for (size_t i = 0; i < particles.fx.size(); ++i) {
            particles.fx[i] += thread_fx[i];
        }
    }

    return 0;
}

但编译器报错,错误信息如下:

MRE.cpp: In function ‘int main()’:
MRE.cpp:31:57: error: expected ‘)’ before ‘.’ token
   31 |     #pragma omp for reduction(vec_double_plus: particles.fx)
      |                                                         ^
      |                                                         )
MRE.cpp:31:48: error: user defined reduction not found for ‘particles’
   31 |     #pragma omp for reduction(vec_double_plus: particles.fx)

请问如何专门为结构体中的std::vector声明归约子句?


解决方法

错误根源

OpenMP的reduction子句不支持直接使用成员访问表达式(如particles.fx)作为归约变量,它要求变量是一个独立的标识符。另外你代码中第二个omp for属于逻辑冗余——归约操作不需要手动循环累加,OpenMP会自动处理合并逻辑。

方法一:用临时变量作为桥梁

先将结构体中的vector赋值给临时变量,对临时变量执行归约,完成后再将结果写回结构体成员:

// g++ -fopenmp MRE.cpp -o MRE
#include <vector>
#include <algorithm>
#include <omp.h>

struct Particles {
    std::vector<double> fx;
};

#pragma omp declare reduction(vec_double_plus : std::vector<double> : \
std::transform(omp_out.begin(), omp_out.end(), omp_in.begin(), omp_out.begin(), std::plus<double>()) \
) initializer(omp_priv = decltype(omp_orig)(omp_orig.size()))

int main() {
    Particles particles;
    
    // Initialize fx vector with 100 elements
    for (int i = 0; i < 100; ++i){
        particles.fx.push_back(0.0);
    }

    // 用临时变量承接结构体的vector
    std::vector<double>& temp_fx = particles.fx;

    #pragma omp parallel reduction(vec_double_plus: temp_fx)
    {
        // Thread-private local vector
        std::vector<double> thread_fx(temp_fx.size(), 0.0);

        #pragma omp for
        for (size_t i = 0; i < temp_fx.size(); ++i){
            thread_fx[i] = 1.0;
        }

        // 直接将线程私有vector合并到临时变量(归约操作)
        std::transform(temp_fx.begin(), temp_fx.end(), thread_fx.begin(), temp_fx.begin(), std::plus<double>());
    }

    return 0;
}

方法二:为结构体类型声明自定义归约

如果需要频繁对Particles结构体的fx成员做归约,可以直接为结构体类型声明归约规则:

// g++ -fopenmp MRE.cpp -o MRE
#include <vector>
#include <algorithm>
#include <omp.h>

struct Particles {
    std::vector<double> fx;
};

// 直接为Particles结构体声明归约,指定对fx成员执行vector求和
#pragma omp declare reduction(particles_fx_plus : Particles : \
std::transform(omp_out.fx.begin(), omp_out.fx.end(), omp_in.fx.begin(), omp_out.fx.begin(), std::plus<double>()) \
) initializer(omp_priv.fx = decltype(omp_orig.fx)(omp_orig.fx.size()))

int main() {
    Particles particles;
    
    // Initialize fx vector with 100 elements
    for (int i = 0; i < 100; ++i){
        particles.fx.push_back(0.0);
    }

    #pragma omp parallel reduction(particles_fx_plus: particles)
    {
        // Thread-private local vector
        std::vector<double> thread_fx(particles.fx.size(), 0.0);

        #pragma omp for
        for (size_t i = 0; i < particles.fx.size(); ++i){
            thread_fx[i] = 1.0;
        }

        // 构造临时Particles对象,将线程私有vector赋值给它的fx成员
        Particles temp_part;
        temp_part.fx = std::move(thread_fx);
        // 合并到全局particles(归约操作)
        std::transform(particles.fx.begin(), particles.fx.end(), temp_part.fx.begin(), particles.fx.begin(), std::plus<double>());
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者Stefan de Souza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:45:55