Ответ немного длиннее, чем необходимо, пожалуйста, не забудьте прочитать все это.Я хотел также включить теоретические части, которые, к сожалению, практически не имеют значения.
Как правило, OpenMP дает большую свободу в выполнении реализации.Это может позволить оптимизировать реализацию, и я призываю вас сделать то же самое: разрешить реализации - компилятору и библиотеке - делать то, что она считает наилучшим, при этом предоставляя ей как можно больше информации.В то же время измерьте производительность сквозным способом и с помощью инструментов, которые понимают OpenMP.Постарайтесь понять, что на самом деле происходит, вместо того, чтобы полагаться на только на ваше интуитивное понимание того, что является оптимальным.
OpenMP 4.5 дает вам один из способов сообщить компилятору, что вы хотите - приоритеты задач.т.е.
#pragma omp single
{
#pragma omp task priority(10)
{
printf("MASTER START\n");
fflush(stdout);
for (int i = 0; i < 1000; ++i)
{
#pragma omp task priority(0)
{
printf("[Thread %d] working on task %d\n", omp_get_thread_num(), i);
Согласно стандарту, задачи с более высоким числовым значением приоритета рекомендуется выполнять перед задачами с более низким приоритетом.Это всего лишь подсказка , и реализация может игнорировать это.
Свобода, предоставляемая стандартом, также позволяет ленивые имперментации .Например, libgomp
(библиотека OpenMP для gcc) имеет жестко запрограммированную логику для немедленного выполнения всех порожденных задач, если в потоке имеется более 64 задач в очереди.Я не верю, что приоритет имеет значение в решении отложить задачу или нет, только для задач в очереди.
Что вы можете наблюдать, используя что-то вроде этого:
int task_count = 1;
#pragma omp parallel
{
#pragma omp single
{
printf("MASTER START (%d)\n", omp_get_thread_num());
fflush(stdout);
for (int i = 0; i < 1000; ++i)
{
#pragma omp atomic
task_count++;
#pragma omp task
{
int q;
#pragma omp atomic capture
q = task_count--;
printf("[Thread %d] working on task %d (%d queued)\n", omp_get_thread_num(), i, q);
Вы можете использоватьэта информация для предотвращения нерестовых задач в первую очередь, если в полете уже слишком много задач.Теперь вы говорите, не имеет значения, если задачи процессора не выполняются.Я сомневаюсь, что как-то они должны в конечном итоге завершить.Таким образом, вы все равно можете избежать слишком большого количества задач процессора.К сожалению, в результате вы получаете решение для конкретной реализации, основанное на понимании того, как работает эта реализация.С другой стороны, это, вероятно, также поможет с другой основной библиотекой OpenMP, используемой Intel / clang.Вы должны выяснить, является ли это лучшим решением, чем развертывание собственного управления очередью задач - будь то OpenMP, pthreads, tbb или что-то еще.