Обеспечение использования функции-члена неконстантного объекта внутри openMP - PullRequest
0 голосов
/ 13 января 2020

Я хочу распараллелить некоторые циклы и широко использовать openMP в других частях кода. Есть объект, который я хочу использовать внутри al oop, который имеет некоторое резервное хранилище (должно быть общим для всех потоков) и некоторое состояние (должно быть приватным для каждого потока).

Представьте себе что-то вроде:

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);
    }
}

Так что либо я трачу много памяти и кеша, либо реализация прерывается из-за совместного использования переменной.

Я думаю, что не могу пометить части общего объекта, а другие как частные или что-нибудь подобное Объект довольно сложный, и состояние используется в разных местах. Есть ли какой-нибудь волшебный c способ заставить объект совместно использовать свое хранилище, но иметь состояние для объекта?

например что-то вроде

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

1 Ответ

1 голос
/ 13 января 2020

Разделите ваши данные на два класса: один содержит все данные, которые будут разделены между потоками, другой - частные данные для каждого потока. Класс для каждого потока будет содержать указатель 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...