首页 > 解决方案 > 使非 const 对象成员函数在 openMP 中可用

问题描述

我想并行化一些循环,并在代码的其他部分广泛使用 openMP。我想在循环中使用一个对象,该对象具有一些后备存储(应该跨线程共享)和一些状态(应该是每个线程私有的)。

想象一下:

class P {
    public:
        // fills storage with 0, 1, 2...
        P(size_t something) {
            for(size_t i = 0; i < something; i++)
                m_storage.push_back(i);
        }

        // finds the closest value in m_storage to probe
        // the algorithm is a stupid dummy, but gets the point across
        float findClosest(float probe) {
            m_state = std::numeric_limits<float>::max();
            auto closest = std::numeric_limits<float>::quiet_NaN();

            for(const auto x: m_storage)
                if(m_state > probe - x) {
                    closest = x;
                    m_state = probe - x;
                }

             return closest;
        }

    private:
        std::vector<float> m_storage;
        float m_state;
}

// sequential access
int main(){
    P p = new P(100);
    std::vector<float> results(5);
    for(size_t i = 0; i<5; i++) {
        results[i] = p.findClosest(i);
    }
}

// parallel access with copy => p.m_storage is copied
int main(){
    P p = new P(100);
    std::vector<float> results(5);
#pragma omp parallel for firstprivate(p)
    for(size_t i = 0; i<5; i++) {
        results[i] = p.findClosest(i);
    }
}

// parallel access with share => p.m_state is altered by multiple threads
int main(){
    P p = new P(100);
    std::vector<float> results(5);
#pragma omp parallel for firstprivate(p)
    for(size_t i = 0; i<5; i++) {
        results[i] = p.findClosest(i);
    }
}

所以要么我浪费了大量的内存和缓存空间,要么实现因为变量的共享使用而中断。

我想我不能将对象的某些部分标记为共享的,而其他部分则标记为私有的或类似的东西。对象相当复杂,状态在不同的地方使用。有什么神奇的方法可以让对象共享它的存储,但每个对象都有状态吗?

例如类似的东西

[...]
    private:
#pragma omp parallel shared
        std::vector<float> m_storage;
#pragma omp parallel private
        float m_state;

标签: c++openmp

解决方案


将您的数据分为两类:一类保存要在线程之间共享的所有数据,另一类保存每个线程的私有数据。per-thread 类将保存一个const指向公共数据的指针或引用(const因为您不想对其进行更改)。

就像是:

class common {
public:
    std::vector<float> m_storage;
    // ...
};

class private_data {
public:
    private_data(const common *cstorage): storage(cstorage) { }
    const common *storage;
    float findClosest(float probe) {
        // ...
    }
};

该类common将有一个实例,传递给所有private_data类。


推荐阅读