2013-08-26 2 views
1

Я хочу сопоставить задачи до трех потоков следующим образом:вложенной параллельности в OpenMP

  1. Каждый из taskA, taskB и taskC должны выполняться отдельными потоками.

  2. taskA имеет подзадачи task(1), task(2) и task(3).

  3. taskB - Замысел task(11), task(12), и task(13).

  4. taskC - Замысел task(21), task(22), и task(23).

  5. Если какое-либо из taskA, taskB и taskC отделки и есть по крайней мере одна из подзадач Не начаты другая задачи, поток, связанный с законченными задачами должны выкрасть подзадачи Не начаты.

Я не смог достичь этой настройки. Все, что я смог сделать следующим MWE. В этом MWE, нити не подчиняются правилам 2, 3, 4.

Вот мой MWE:

double task(int taskid) { 
    int tid = omp_get_thread_num(); 
    int nthreads = omp_get_num_threads(); 
    printf("%d/%d: taskid=%d\n", tid, nthreads, taskid); 

    int i; 
    double t = 1.1; 
    for(i = 0; i < 10000000*taskid; i++) { 
     t *= t/i; 
    } 
    return t; 
} 

double taskA() { 
    int tid = omp_get_thread_num(); 
    int nthreads = omp_get_num_threads(); 
    printf("%s %d/%d\n", __FUNCTION__, tid, nthreads); 
    double a, b, c; 
    //#pragma omp parallel 
    //#pragma omp single 
    { 
    #pragma omp task untied shared(a) 
    a=task(1); 
    #pragma omp task untied shared(b) 
    b=task(2); 
    #pragma omp task untied shared(c) 
    c=task(3); 
    } 
    return a+b+c; 
} 

double taskB() { 
    int tid = omp_get_thread_num(); 
    int nthreads = omp_get_num_threads(); 
    printf("%s %d/%d\n", __FUNCTION__, tid, nthreads); 
    double a, b, c; 
    //#pragma omp parallel 
    //#pragma omp single 
    { 
    #pragma omp task untied shared(a) 
    a=task(11); 
    #pragma omp task untied shared(b) 
    b=task(12); 
    #pragma omp task untied shared(c) 
    c=task(13); 
    } 
    return a+b+c; 
} 

double taskC() { 
    int tid = omp_get_thread_num(); 
    int nthreads = omp_get_num_threads(); 
    printf("%s %d/%d\n", __FUNCTION__, tid, nthreads); 
    double a, b, c; 
    //#pragma omp parallel 
    //#pragma omp single 
    { 
    #pragma omp task untied shared(a) 
    a=task(21); 
    #pragma omp task untied shared(b) 
    b=task(22); 
    #pragma omp task untied shared(c) 
    c=task(23); 
    } 
    return a+b+c; 
} 
int main() { 
    omp_set_num_threads(3); 
    double a,b,c; 

    #pragma omp parallel 
    #pragma omp single 
    { 
     #pragma omp task untied 
     a=taskA(); 
     #pragma omp task untied 
     b=taskB(); 
     #pragma omp task untied 
     c=taskC(); 
    } 
    #pragma omp taskwait 
    printf("%g %g %g\n", a, b, c); 
    return 0; 
} 

Составитель как:

icpc -Wall -fopenmp -O2 -o nestedomp nestedomp.c 

Выход:

taskC 1/3 
1/3: taskid=21 
taskA 2/3 
taskB 0/3 
0/3: taskid=23 
2/3: taskid=22 
1/3: taskid=1 
1/3: taskid=2 
2/3: taskid=3 
0/3: taskid=11 
1/3: taskid=12 
2/3: taskid=13 

Здесь нить 0 начинает обрабатывать задачу 23, однако она должна начать обработку 1 или 11.

+1

Почему вы не переформатируете эту проблему по принципу парадигмы мастер-раб? Это будет соответствовать вашим требованиям. – vrume21

+0

Уважаемый @ bam54, я был бы очень признателен, если бы вы могли указать мне пример или решение, основанное на парадигме master-slave. Кстати, у меня есть интуиция о том, что вы не используете очереди, блокировки, общие переменные и т. Д., Что может ухудшить параллельную производительность, особенно в системе с 48 ядрами. Я предпочел бы использовать только поддерживаемые конструкции, которые должны выполняться очень хорошо. – Kadir

+0

Конструкция OpenMP, которая приходит на ум, - это расписание (динамическое, [, chunk]). Не могли бы вы просто поднять все подзадачи в один список, который можно повторить? Затем вы можете использовать параллель для расписания (dynamic, [, chunk]), которая будет обрабатывать части работы по потокам по мере их завершения. Похоже, что из кода, который вы указали, что группировка подзадач в задачи не имеет значения в отношении их обработки. – vrume21

ответ

0

Вы можете использовать идентификатор потока для структуры распределения работы:

#pragma omp parallel num_threads(3) 
{ 
int tid = omp_get_thread_num(); 

if (tid == 0) 
    // Task 0 
} else if (tid == 1) { 
    // Task 1 
} else 
    // Task 2 
} 

Вы можете установить количество потоков в соответствии с вашими потребностями и ввести гнездятся на уровне задач.

+1

Это решение не обеспечивает кражу работы. – Kadir

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