Ошибка openMP C ++ с вектором threadprivate - PullRequest
0 голосов
/ 12 апреля 2020
#include<iostream>
#include<vector>
#include<ctime>
#include<cmath>
#include<omp.h>
#include<array>
using namespace std;

double counter = 0;
vector<int> vec;

vector<double> reduction;
#pragma omp threadprivate(reduction)


vector<double> eet;
int fish;


void mario( int current_node, int current_depth) {
    int q = current_node % 4;
    #pragma omp simd
    for( int i = 3 ; i < current_node; i+=4){
        reduction[i]+=4;
        mario(i, current_depth);
        mario(i - 1,current_depth);
        mario(i - 2,current_depth);
        mario(i - 3,current_depth);
    }
    #pragma omp simd
    for(int x = 1; x <= q; x++){
        reduction[0]++;
        mario(current_node - x,current_depth);
    }
    #pragma omp task firstprivate(current_node,current_depth)
    {
        if(current_depth > 0){
                int new_depth = current_depth - 1;
                #pragma omp simd
                for(int i = current_node;i <= vec[current_node];i++){
                    reduction[i]++;
                    mario(i + 1,new_depth);
            }
        } 
    } 
}


int main() {
    omp_proc_bind_true;
    omp_set_dynamic(0);
    int nodes;
    int timesteps;
    int threadz;
    cout << "enter number of nodes" << endl;

    cin >> nodes;

    cout << "enter number of timesteps" << endl;

    cin >> timesteps;

    cout << "enter number threads" << endl;

    cin >> threadz;

    omp_set_num_threads(threadz);

    int mushroom = nodes - 2;
    fish = nodes - 1;

    vec.assign( nodes, mushroom );

    clock_t t = clock();

    vector<double> zed(mushroom + 1 , 0 );

    eet = zed;
    reduction = eet;
    #pragma omp parallel copyin(reduction)
    {

        #pragma omp single
        {
            mario(nodes - 1, timesteps - 1);
        }

        #pragma omp critical
        {
            #pragma omp simd
            for(int x = 0; x < zed.size();x++){
                eet[x] += reduction[x];
            }
        }
        #pragma omp barrier
    }
    for(int j = 0; j < eet.size(); j++){
            counter += eet[j];
    }
    t = clock() - t;
    double time_taken = ((double)t) / CLOCKS_PER_SEC;
    cout << "mario took " << fixed << counter << " steps" << endl;
    cout << "It took him " << time_taken << " seconds" << endl;
    return 0;
}

В моем коде я объявляю сокращение вектора: vector<double> reduction;

Затем я немедленно использую threadprivate: #pragma omp threadprivate(reduction), но когда я компилирую свой код, я получаю ошибки.

ошибка: 'extension' объявил 'threadprivate' после первого использования

13 | #pragma omp threadprivate (сокращение)

ошибка: для параметра "extension" должно быть значение "threadprivate" для "copyin"

82 | #pragma omp параллельное копирование (сокращение)

Что вызывает эти ошибки? Я только что объявил переменную, ничего не делая.

Можно ли избежать ошибки?

Существуют ли другие методы сокращения задач openMP для рекурсивных функций

или альтернативные методы борьбы с проблемой?

Есть ли что-то принципиально неправильное в том, как я пытаюсь написать свой код?

Я использую g cc 9.3

, извините, если мой вопрос неясен, пожалуйста, пожалуйста предложить улучшения.

1 Ответ

0 голосов
/ 14 апреля 2020

Обоснование решения, которое работает только с g cc, это, к сожалению, просто обходной путь, а не правильное решение.

#include<iostream>
#include<vector>
#include<ctime>
#include<cmath>
#include<omp.h>
#include<array>
#include<thread>
using namespace std;

double counter = 0;
vector<int> vec;
thread_local vector<double> reduction;

vector<double> eet;
int fish;



void mario( int current_node, int current_depth) {
    int q = current_node % 4;
    #pragma omp simd
    for( int i = 3 ; i < current_node; i+=4){
        reduction[i]+=4;
        mario(i, current_depth);
        mario(i - 1,current_depth);
        mario(i - 2,current_depth);
        mario(i - 3,current_depth);
    }
    #pragma omp simd
    for(int x = 1; x <= q; x++){
        reduction[0]++;
        mario(current_node - x,current_depth);
    }
    #pragma omp task firstprivate(current_node,current_depth)
    {
        if(current_depth > 0){
                int new_depth = current_depth - 1;
                #pragma omp simd
                for(int i = current_node;i <= vec[current_node];i++){
                    reduction[i]++;
                    mario(i + 1,new_depth);
            }
        } 
    } 
}



int main() {
    omp_proc_bind_true;
    omp_set_dynamic(0);
    int nodes;
    int timesteps;
    int threadz;
    cout << "enter number of nodes" << endl;

    cin >> nodes;

    cout << "enter number of timesteps" << endl;

    cin >> timesteps;

    cout << "enter number threads" << endl;

    cin >> threadz;

    omp_set_num_threads(threadz);
    int mushroom = nodes - 2;
    fish = nodes - 1;
    vec.assign( nodes, mushroom );
    clock_t t = clock();
    vector<double> zed(mushroom + 1 , 0 );
    eet = zed;
    #pragma omp parallel
    {
        reduction = zed;
        #pragma omp barrier
        #pragma omp single
        {
            mario(nodes - 1, timesteps - 1);
        }
        #pragma omp critical
        {
            for(int x = 0; x < reduction.size();x++){
                eet[x] += reduction[x];
            }

        }
        #pragma omp barrier
    }
    for(int j = 0; j < eet.size(); j++){
            counter += eet[j];
    }
    t = clock() - t;
    double time_taken = ((double)t) / CLOCKS_PER_SEC;
    cout << "mario took " << fixed << counter << " steps" << endl;
    cout << "It took him " << time_taken << " seconds" << endl;
    return 0;
}

Это ужасный метод, работающий, по-видимому, g * Реализация c ++ 1012 * использует потоки POSIX, а g cc реализация openMP - это просто POSIX под капотом. source: Использование C ++ 11 thread_local с другими параллельными библиотеками

То же самое с g cc, если переменная отправляется в локальное хранилище потока таким образом, что это эквивалентно переменной 'threadprivate' в openMP.

Кто-то еще, пожалуйста, предложите правильное решение.

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