Практическое руководство. Задание определенных политик планировщика

Политики планировщика позволяют управлять стратегией, которую планировщик использует при управлении задачами. В этом разделе показано, как использовать политику планировщика для увеличения приоритета потока задачи, которая выводит индикатор хода выполнения в консоль.

Пример использования настраиваемых политик планировщика вместе с асинхронными агентами см. в разделе "Практическое руководство. Создание агентов, использующих определенные политики планировщика".

Пример

В следующем примере выполняются две задачи параллельно. Первая задача вычисляет n-й номер Fibonacci. Вторая задача выводит индикатор хода выполнения в консоль.

Первая задача использует рекурсивную декомпозицию для вычисления числа Fibonacci. То есть каждая задача рекурсивно создает подзадачи для вычисления общего результата. Задача, использующая рекурсивное декомпозиция, может использовать все доступные ресурсы и тем самым голодать другие задачи. В этом примере задача, которая печатает индикатор хода выполнения, может не получать своевременный доступ к вычислительным ресурсам.

Чтобы предоставить задачу, которая выводит сообщение о ходе выполнения, справедливый доступ к вычислительным ресурсам, в этом примере используются шаги, описанные в разделе "Практическое руководство. Управление экземпляром планировщика для создания экземпляра планировщика с настраиваемой политикой". Пользовательская политика указывает приоритет потока, который должен быть самым высоким классом приоритета.

В этом примере для печати индикатора хода выполнения используется классы параллелизма::call и параллелизма::timer . Эти классы имеют версии своих конструкторов, которые принимают ссылку на объект параллелизма::Scheduler , который планирует их. В примере используется планировщик по умолчанию для планирования задачи, вычисляющей номер Fibonacci и экземпляр планировщика, чтобы запланировать задачу, которая выводит индикатор хода выполнения.

Чтобы проиллюстрировать преимущества использования планировщика с пользовательской политикой, в этом примере выполняется общая задача в два раза. В примере сначала используется планировщик по умолчанию для планирования обоих задач. Затем в примере используется планировщик по умолчанию для планирования первой задачи и планировщика, имеющего настраиваемую политику для планирования второй задачи.

// scheduler-policy.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <agents.h>
#include <iostream>

using namespace concurrency;
using namespace std;

// Computes the nth Fibonacci number.
// This function illustrates a lengthy operation and is therefore
// not optimized for performance.
int fibonacci(int n)
{
   if (n < 2)
      return n;

   // Compute the components in parallel.
   int n1, n2;
   parallel_invoke(
      [n,&n1] { n1 = fibonacci(n-1); },
      [n,&n2] { n2 = fibonacci(n-2); }
   );
  
   return n1 + n2;
}

// Prints a progress indicator while computing the nth Fibonacci number.
void fibonacci_with_progress(Scheduler& progress_scheduler, int n)
{
   // Use a task group to compute the Fibonacci number.
   // The tasks in this group are scheduled by the current scheduler.
   structured_task_group tasks;

   auto task = make_task([n] {
      fibonacci(n);
   });
   tasks.run(task);

   // Create a call object that prints its input to the console.
   // This example uses the provided scheduler to schedule the 
   // task that the call object performs.
   call<wchar_t> c(progress_scheduler, [](wchar_t c) { 
      wcout << c; 
   });

   // Connect the call object to a timer object. The timer object
   // sends a progress message to the call object every 100 ms.
   // This example also uses the provided scheduler to schedule the 
   // task that the timer object performs.
   timer<wchar_t> t(progress_scheduler, 100, L'.', &c, true);
   t.start();

   // Wait for the task that computes the Fibonacci number to finish.
   tasks.wait();

   // Stop the timer.
   t.stop();

   wcout << L"done" << endl;
}

int wmain()
{  
   // Calculate the 38th Fibonacci number.
   const int n = 38;

   // Use the default scheduler to schedule the progress indicator while 
   // the Fibonacci number is calculated in the background.

   wcout << L"Default scheduler:" << endl;
   fibonacci_with_progress(*CurrentScheduler::Get(), n);

   // Now use a scheduler that has a custom policy for the progress indicator.
   // The custom policy specifies the thread priority to the highest 
   // priority class.
   
   SchedulerPolicy policy(1, ContextPriority, THREAD_PRIORITY_HIGHEST);
   Scheduler* scheduler = Scheduler::Create(policy);

   // Register to be notified when the scheduler shuts down.
   HANDLE hShutdownEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
   scheduler->RegisterShutdownEvent(hShutdownEvent);

   wcout << L"Scheduler that has a custom policy:" << endl;
   fibonacci_with_progress(*scheduler, n);

   // Release the final reference to the scheduler. This causes the scheduler
   // to shut down.
   scheduler->Release();

   // Wait for the scheduler to shut down and destroy itself.
   WaitForSingleObject(hShutdownEvent, INFINITE);

   // Close the event handle.
   CloseHandle(hShutdownEvent);
}

В этом примере формируются следующие данные:

Default scheduler:
...........................................................................done
Scheduler that has a custom policy:
...........................................................................done

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

Компиляция кода

Скопируйте пример кода и вставьте его в проект Visual Studio или вставьте его в файл с именем scheduler-policy.cpp , а затем выполните следующую команду в окне командной строки Visual Studio.

cl.exe /EHsc scheduler-policy.cpp

См. также

Политики планировщика
Практическое руководство. Управление экземпляром планировщика
Практическое руководство. Создание агентов, использующих определенные политики планировщика