OpenMP назначает выполнение функции потоку?

В основном мне нужно, чтобы главный поток продолжал выполнять некоторую операцию на основе значения некоторых глобальных переменных, которые могут быть отредактированы (через некоторые выбранные интервалы) вторичным потоком. Что-то типа:

vector<int> mySharedVar;

void secondaryThreadFunction() {
   Do some operations
   And update mySharedVar if necessarily  
}

int main() {
 int count = 0;
 while(true) {
    count++;

    if (count%100) {  //> Each 100 iterations run a parallel thraed
      //> RUN secondaryThreadFunction in a separateThread
    }

    this is the main thread that based its operation on mySharedVar
 }
}

Какая команда openmp запускает один параллельный поток с secondaryThreadFunction(); ?

Есть ли другой лучший способ, чем этот:

#pragma omp parallel num_threads(2)
    {
        int i = omp_get_thread_num();

        if (i == 0){
            mainThread();
        }
        if (i == 1 || omp_get_num_threads() != 2){
            secondaryThreadFunction();
        }
    }

person dynamic    schedule 18.07.2012    source источник
comment
Я полагаю, что разделы OpenMP немного менее хакерские.   -  person Mysticial    schedule 18.07.2012
comment
@Mysticial: привет, лол, я взял этот образец из твоего ответа: D stackoverflow.com/questions/7876156/ в любом случае, не могли бы вы показать мне образец? :D   -  person dynamic    schedule 18.07.2012
comment
лол, этот вопрос, кажется, имеет хороший пример: stackoverflow.com/questions/2770911/   -  person Mysticial    schedule 18.07.2012
comment
Большое спасибо, этот ответ довольно ясен   -  person dynamic    schedule 18.07.2012
comment
@Mysticial: в любом случае разделы кажутся почти такими же, как в параллельном примере. Есть ли другой способ запустить функцию или класс в отдельном потоке? Что-то вроде java Thread.run();? Мне просто нужно 2 очень простых потока, работающих вечно, где второй поток обновляет некоторые глобальные переменные один раз в 200 мс (или когда главные потоки отправляют ему сигнал)   -  person dynamic    schedule 18.07.2012
comment
Звучит как задача для реального потокового API. OpenMP в основном предназначен для параллелизма в стиле fork/join. Таким образом, вам в основном нужно обернуть всю вашу программу в параллельную область.   -  person Mysticial    schedule 18.07.2012


Ответы (1)


Вот что я придумал:

#include <omp.h>
#include <unistd.h>
#include <vector>
#include <iostream>

std::vector<int> mySharedVar(10);

void secondaryThreadFunction() {
  mySharedVar[5]++;
}

int main() {
  int  i = 0 ;

#pragma omp parallel sections shared(mySharedVar) private(i)
  {
#pragma omp section
    //main thread
    {
      while( mySharedVar[5] < 10) {
        std::cout << "main: ";
        for(i=0; i < mySharedVar.size(); ++i){
          std::cout << mySharedVar[i] << " ";
        }
        std::cout << std::endl;
        usleep(1.e5); // wait 0.1 seconds
      }
    }
#pragma omp section
    {  
      while( mySharedVar[5] < 10) {
        secondaryThreadFunction();  
        usleep(3.e5); // wait 0.3 seconds
      }
    }
  }
}

скомпилировать и запустить с g++ -fopenmp test_omp_01.cc && ./a.out

выход:

main: 0 0 0 0 0 1 0 0 0 0 
main: 0 0 0 0 0 1 0 0 0 0 
main: 0 0 0 0 0 1 0 0 0 0 
main: 0 0 0 0 0 2 0 0 0 0 
main: 0 0 0 0 0 2 0 0 0 0 
main: 0 0 0 0 0 2 0 0 0 0 
main: 0 0 0 0 0 3 0 0 0 0 
main: 0 0 0 0 0 3 0 0 0 0 
main: 0 0 0 0 0 3 0 0 0 0 
main: 0 0 0 0 0 4 0 0 0 0 
main: 0 0 0 0 0 4 0 0 0 0 
main: 0 0 0 0 0 4 0 0 0 0 
main: 0 0 0 0 0 5 0 0 0 0 
main: 0 0 0 0 0 5 0 0 0 0 
main: 0 0 0 0 0 5 0 0 0 0 
main: 0 0 0 0 0 6 0 0 0 0 
main: 0 0 0 0 0 6 0 0 0 0 
main: 0 0 0 0 0 6 0 0 0 0 
main: 0 0 0 0 0 7 0 0 0 0 
main: 0 0 0 0 0 7 0 0 0 0 
main: 0 0 0 0 0 7 0 0 0 0 
main: 0 0 0 0 0 8 0 0 0 0 
main: 0 0 0 0 0 8 0 0 0 0 
main: 0 0 0 0 0 8 0 0 0 0 
main: 0 0 0 0 0 9 0 0 0 0 
main: 0 0 0 0 0 9 0 0 0 0 
main: 0 0 0 0 0 9 0 0 0 0 
person steffen    schedule 18.07.2012
comment
спасибо +1! нужно ли ставить shared(mySharedVar) и private(i) ? - person dynamic; 19.07.2012
comment
да. Как иначе компилятор узнает, что вы не хотите, чтобы оба потока увеличивали i? - person steffen; 19.07.2012
comment
Вы можете поместить int i = 0; в поток, который его использует, и не нужно ставить private(i) ? Что касается общего доступа (mySharedVar), он нужен? mySharedVar - это глобальные переменные, поэтому компилятор должен знать, что он является общим - person dynamic; 19.07.2012
comment
По поводу i вы правы. Что касается вектора, не обязательно каждая переменная, объявленная вне параллельного блока, должна быть общей. Что, если вы хотите вычислить начальное значение для переменной итерации вне блока, а затем использовать ее независимо каждым потоком... - person steffen; 19.07.2012
comment
steffen У меня есть вопрос: подумайте, если обоим потокам нужно что-то записать в mySharedVar, как я могу получить мьютекс, чтобы операция над ним была атомарной? (чтобы избежать условий гонки) - person dynamic; 20.07.2012
comment
может быть, именованный критический раздел? - person dynamic; 20.07.2012
comment
OpenMP позаботится об этом. Вот почему вы объявляете его «общим». - person steffen; 20.07.2012
comment
Хм, может быть, для одной инструкции openmp знает, но если у меня есть что-то вроде: if (mySharedVar[5] < 2) mySharedVar[5] = 3;, пока другой поток обновляет это значение, я считаю, что мне нужен критический - person dynamic; 20.07.2012