Опубликован: 05.03.2013 | Уровень: для всех | Доступ: платный
Самостоятельная работа 6:

Знакомство с "Визуализатором параллелизма" в Visual Studio 12

< Лекция 8 || Самостоятельная работа 6 || Лекция 9 >
Аннотация: Реализация PLINQ-запросов.

Задачи

  1. Выполните анализ загруженности вычислительной системы при разном режиме ожидания потока.
  2. Выполните анализ автоматического распараллеливания циклической обработки шаблоном Parallel.For.
  3. Выполните анализ распараллеливания PLINQ-запросов.

Методические указания

Среда разработки Visual Studio 12 содержит полезный инструмент для анализа эффективности выполнения параллельной программы – "Визуализатор параллелизма". Для запуска инструмента на вкладке "Анализ" запускаем "Визуализатор параллелизма" -> "Выполнить анализ с текущим процессом". Инструмент запускает программу и собирает информацию о её фактическом исполнении на данной вычислительной системе. Основные вкладки результатов: "Использование", "Потоки", "Ядра".

Использование ЦП

Вкладка содержит информацию об общей загрузке ЦП приложением в течение всего интервала выполнения.


Потоки

Вкладка "Потоки" выводит информацию о выполнении потоков, как пользовательских, так и рабочих потоков пула. Если в программе не используются объекты ThreadPool, Parallel, Task, то рабочие потоки простаивают. Для удобства восприятия информацию об отдельных потоках, например, простаивающих, можно скрыть. График "Сводка по потокам" суммирует время нахождения потоков в том или ином состоянии.


Ядра

Вкладка "Ядра" позволяет проанализировать перемещение потоков по фактическим исполнителям - ядрам процессора.


Анализ блокировки потоков

Применение "Визуализатора" позволяет исследовать особенности разных средств синхронизации.

Следующие фрагменты осуществляют блокировку основного потока с помощью цикла ожидания (активная блокировка) и с помощью встроенного механизма Join с выгружением контекста потока.

// Фрагмент 1 
 Thread t = new Thread(() => {  
  for (int i=0; i<10000; i++) 
   for(int j =0; j < 100; j++) 
    a[i] += Math.Sin(j) + i; 
  }); 
  
t.Start(); 
// Цикл ожидания 
 while(t.IsAlive) ; 
  
 // Фрагмент 2 
 Thread t = new Thread(() => { 
  for (int i=0; i<10000; i++) 
   for(int j =0; j < 100; j++) 
    a[i] += Math.Sin(j) + i; 
  
  }); 
 t.Start(); 
 t.Join(); 
 

Окно "Использование ЦП" иллюстрирует основной недостаток циклической блокировки – полезную работу осуществляет один поток, а вычислительные ресурсы заняты двумя потоками

Циклическая блокировка


Блокировка Join


При Join-блокировке основной поток №4808 почти все время находится в состоянии "Синхронизация", ожидая завершения потока №4848.


Вкладка "ядра" позволяет зафиксировать интересную особенность блокировок. При циклическом ожидании работают два потока (рабочий и основной), на двуядерной системе потоки практически не перемещаются между ядрами.


При блокировке основного потока методом Join, вычислительная система с двумя ядрами полностью предоставлена одному рабочему потоку. Операционная система активно перемещает поток с одного ядра на другое.



При таком выполнении существуют дополнительные накладные расходы, связанные с переключением контекста между ядрами (процент переключений между ядрами 48.16% от общего числа переключений).

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

Блокировка SpinWait комбинирует два типа ожидания.

// Фрагмент 1 
 Thread t = new Thread(() => {  
  for (int i=0; i<10000; i++) 
   for(int j =0; j < 100; j++) 
    a[i] += Math.Sin(j) + i; 
  }); 
  
t.Start(); 
// Цикл ожидания 
 SpinWait.SpinUntil(() => !t.IsAlive); 
  
 

В начале цикла ожидания выполняется несколько прокруток, после чего ожидающий поток выгружается, освобождая вычислительные ресурсы.

Анализ выполнения объектов библиотеки TPL

Применение объектов TPL для распараллеливания скрывает от программиста работу по созданию и синхронизации потоков. "Визуализатор параллелизма" позволяет получить основную информацию о действиях среды выполнения по распараллеливанию задач.

Метод Parallel.For автоматически распределяет итерации цикла по рабочим потокам. Вкладка "Потоки" раскрывает особенности выполнения параллельной циклической обработки.


Специальная строка System.Threading.Tasks указывает на вызов и работу объекта TPL. В окне "Сводка" отображается итоговая информация о выполнении цикла. Рассматривая работу потоков, видим, что в каждый момент времени работают только два потока, другие потоки вытесняются. Основной поток также участвует в обработке цикла. Сначала для обработки используются два дополнительных рабочих потока, спустя какое-то время в работу включается еще один поток.

< Лекция 8 || Самостоятельная работа 6 || Лекция 9 >
Светлана Папшева
Светлана Папшева
Россия
Валерий Субботин
Валерий Субботин
Украина