Я хочу сопоставить задачи до трех потоков следующим образом:вложенной параллельности в OpenMP
Каждый из
taskA
,taskB
иtaskC
должны выполняться отдельными потоками.taskA
имеет подзадачиtask(1)
,task(2)
иtask(3)
.taskB
- Замыселtask(11)
,task(12)
, иtask(13)
.taskC
- Замыселtask(21)
,task(22)
, иtask(23)
.Если какое-либо из
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.
Почему вы не переформатируете эту проблему по принципу парадигмы мастер-раб? Это будет соответствовать вашим требованиям. – vrume21
Уважаемый @ bam54, я был бы очень признателен, если бы вы могли указать мне пример или решение, основанное на парадигме master-slave. Кстати, у меня есть интуиция о том, что вы не используете очереди, блокировки, общие переменные и т. Д., Что может ухудшить параллельную производительность, особенно в системе с 48 ядрами. Я предпочел бы использовать только поддерживаемые конструкции, которые должны выполняться очень хорошо. – Kadir
Конструкция OpenMP, которая приходит на ум, - это расписание (динамическое, [, chunk]). Не могли бы вы просто поднять все подзадачи в один список, который можно повторить? Затем вы можете использовать параллель для расписания (dynamic, [, chunk]), которая будет обрабатывать части работы по потокам по мере их завершения. Похоже, что из кода, который вы указали, что группировка подзадач в задачи не имеет значения в отношении их обработки. – vrume21