2017-01-11 3 views
3

Я запускаю цикл for с openmp с динамической балансировкой нагрузки. Я хотел бы напечатать, сколько задач/итераций обрабатывается каждый поток в конце программы. Цикл выглядит следующим образом:Вычислить число итераций в цикле openmp с динамическим расписанием

chunk=1; 
#pragma omp parallel for schedule(dynamic,chunk) private(i) 
for(i=0;i<n;i++){ 
//loop code 
} 
+0

'threadprivate' - это самое простое решение. –

ответ

3

Ничего проще. Просто разделить комбинированную parallel for директивы на два отдельные конструкции, что позволяет добавлять дополнительный код до и после цикла:

#pragma omp parallel 
{ 
    int iters = 0; 
    #pragma omp for schedule(dynamic,chunk) 
    for (int i = 0; i < n; i++) { 
     ... 
     iters++; 
    } 
    #pragma omp critical 
    printf("Thread %d did %d iterations\n", omp_get_thread_num(), iters); 
} 
+0

Не должно быть '#pragma omp критическое' перед' printf'. Кроме того, ОП сказал «в конце программы», поэтому ОП может означать, что он/она хочет сохранить результаты и распечатать их позже, за пределами параллельной области. –

+0

«Ничего проще». 'threadprivate' проще, а также не требует изменения структуры кода. –

+0

'threadprivate' требует статическую/глобальную переменную, которая открывает еще одну банку червей. –

0

Используйте частный индивидуальный счетчик для каждого потока. Другого пути нет.

Что-то вроде

int workload[n_threads] = {0, ...}; 
#pragma omp parallel for schedule(dynamic) private(i) 
for(int i=0;i<n;i++){ 
    //loop code 
    workload[omp_get_thread_num()]++; 
} 
+2

... Ложное разделение ... –

1

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

#include <stdio.h> 
#include <omp.h> 

int iters; 
#pragma omp threadprivate(iters) 

int main(void) { 
    omp_set_dynamic(0); //Explicitly turn off dynamic threads 
    int i; 
    int n = 10000; 
    #pragma omp parallel for schedule(dynamic) 
    for(i=0; i<n; i++) { 
    iters++; 
    } 
    #pragma omp parallel 
    #pragma omp critical 
    printf("Thread %d did %d iterations\n", omp_get_thread_num(), iters); 
} 

Это сложное решение, которое также требует, чтобы вы изменили структуру своего кода.

#include <stdio.h> 
#include <stdlib.h> 
#include <omp.h> 

int main(void) { 
    int i; 
    int n = 100; 
    int nthreads; 
    int *aiters; 
    #pragma omp parallel 
    { 
    nthreads = omp_get_num_threads(); 
    #pragma omp single 
    aiters = malloc(sizeof *aiters * nthreads); 
    int iters = 0; 
    #pragma omp for schedule(dynamic) 
    for(i=0; i<n; i++) { 
     iters++; 
    } 
    aiters[omp_get_thread_num()]=iters; 
    } 
    for(i=0; i<nthreads; i++) 
    printf("Thread %d did %d iterations\n", i, aiters[i]); 
    free(aiters); 
} 
+0

Нет гарантии, что две параллельные области в вашем первом образце будут выполняться с таким же количеством потоков. _dyn-var_ должно быть явно установлено _false_. –

+0

@HristoIliev, я исправил его, я думаю, используя 'omp_set_dynamic (0)'.Я не знал, что количество потоков может динамически меняться между параллельными областями без явного указания OpenMP для этого. Это может быть правдой в принципе, но я не знаю, видел ли я когда-либо это на практике. У вас есть? –

+0

@HristoIliev, почему вы не указали это [здесь] (http://stackoverflow.com/questions/18719257/parallel-cumulative-prefix-sums-in-openmp-communicating-values-between-thread#comment27598031_18719257) «schedule (static) имеет специальные свойства, гарантированные стандартом, например повторяемый шаблон распределения». Я не могу полагаться на график (статический), имеющий тот же повторяемый дистрибутив, если число динамических изменений потоков между параллельными областями. –

Смежные вопросы