Оптимизация ПО для поддержки технологии Hyper-Threading с помощью OpenMP™ и Intel® Threading Toolkit Максим Перминов maxim.perminov@intel.com Разработчик ПО, корпорация Intel 1 Содержание Технология Hyper-Threading – многопоточность – OpenMP™ Наша первая программа на OpenMP Наша первая корректная программа на OpenMP Оптимизация производительности с помощью Intel® Threading Toolkit 2 Как работает технология HT Без HyperThreading Физические процессоры Логические Физический процессор процессоры распределение ресурсов видимые для ОС Время На выходе Ресурс 1 Поток 2 Поток 1 Ресурс 2 С HyperThreading Ресурс 3 Ресурс 1 Ресурс 2 + Ресурс 3 Лучшее использование ресурсов и более высокая производительность благодаря двум одновременно обрабатываемым потокам 3 Разбивайте Ваше приложение на несколько потоков Что? Стратегия многопоточности – Распараллеливание задачи – Распараллеливание данных Как? Внедрение многопоточности – Языки программирования (C#, Java) – API / Библиотека (Win32, P-потоки, MPI) – Расширение языков программирования (OpenMP) OpenMP позволяет ускорить распараллеливание задач и данных 4 Что такое OpenMP™? Расширение компилятора для легкого распараллеливания НЕ МЕНЯЕТ КОД C/C++ Три компоненты: – #pragma (директива компилятора) – самое важное – API и библиотека Runtime – Переменные окружения Преимущества: – – – – Легкий путь использования Hyper-Threading Переносимость и стандартизация Постепенное распараллеливание Специальные инструменты профилирования 5 Модель программирования Параллельность типа «разветвлениесоединение»: – основной поток порождает группу дополнительных потоков – Группа потоков соединяется в конце области распараллеливания Вся память (переменные) совместно используется по умолчанию Распараллеливание можно осуществлять шаг за шагом основной поток – Последовательная программа разворачивается в параллельную группа потоков Области распараллеливания 6 Наша первая программа на OpenMP™ Все прагмы OpenMP™ начинаются с omp Прагма parallel порождает группу из n потоков Все внутри исполняется n раз! Вся память используется совместно! void func() { int a, b, c, d; void func() { int a, b, c, d; #pragma omp parallel { a = a + b; c = c + d; } } a = a + b; c = c + d; } 7 Упражнение 1: Hello OpenMP™ Изначальный код – Откройте проект PrimeHT.dsp – Скомпилируйте и запустите, используя стандартный компилятор Microsoft* – Скомпилируйте и запустите, используя компилятор Intel® Compiler; отметьте результаты Hello OpenMP™ – Найдите в PrimeHT.cpp цикл, серьезно влияющий на производительность – Создайте вокруг него область распараллеливания OpenMP Оставьте код тайминга вне области распараллеливания – Включите в Intel Compiler поддержку OpenMP опция /Qopenmp – Скомпилируйте и запустите – Можете объяснить результаты? 8 Приписывание задач потокам Разделяющие работу прагмы приписывают задачи потокам Прагма sections приписывает неитеративные задачи void func() { int a, b, c, d; #pragma omp parallel { #pragma omp sections { #pragma omp section a = a + b; //one thread #pragma omp section c = c + d; //another thread } } } 9 Прагмы, разделяющие задачу Прагмы, разделяющие задачу, можно объединять с прагмой parallel void func() { int a, b, c, d; #pragma omp parallel sections { #pragma omp section a = a + b; //one thread #pragma omp section c = c + d; //another thread } } Две функции, исполняющиеся параллельно: #pragma omp parallel sections { #pragma omp section do_compress(); #pragma omp section do_encrypt(); } #pragma omp parallel sections Распараллеливание на уровне задания! 10 Упражнение 2: Parallel Sections Разбейте основной цикл на два например, from .. to/2 и to/2 .. to Превратите общую область в конструкцию «parallel sections» Поместите каждый подцикл в свою секцию Скомпилируйте и запустите; (попытайтесь) объяснить результат 11 Разделение работы на циклах Прагма for приписывает циклы потокам Есть несколько способов сделать это… Между прочим, что делается в приведенном примере? void func() { int a[N], sum = 0; #pragma omp parallel for for (int i = 0; i < N; i++) { sum += a[i]; } } #pragma omp parallel for Распараллеливание на уровне данных! 12 Упражнение 3: Parallel For Восстановите один основной цикл from .. to Превратите общую область в конструкцию «parallel for» Скомпилируйте и запустите Объясните результат 13 Правила разделения переменных Неявное правило 1: Все переменные, определенные вне omp parallel, являются глобальными для всех потоков Неявное правило 2: Все переменные, определенные внутри omp parallel, являются локальными для каждого потока Неявное исключение : В прагме omp for, счетчик цикла всегда локален для каждого потока Явное правило 1: Переменные, приведенные в shared(), являются глобальными для всех потоков Явное правило 2: Переменные, приведенные в private(), являются локальными для каждого потока 14 Какие переменные локальные, а какие глобальные? void func() { int a, i; #pragma omp parallel for \ shared(c) private(d, e) for (i = 0; i < N; i++) { int b, c, d, e; a = a + b; c = c + d * e; } } 15 Упражнение 4: области действия переменных С помощью указанных выше правил установите области действия переменных в основном цикле Скомпилируйте и запустите Объясните результат 16 Проблема синхронизации Команды процессора Код C mov eax, [sum] add eax, 1 mov [sum], eax sum++; ветвь 1 такт ветвь 1 исполняет eax сумма s ветвь 2 eax ветвь 1 исполняет s s s add eax, 1 s+1 s s+1 mov [sum], eax s+1 s+1 s+1 s+1 s+1 t+0 mov eax, [sum] t+1 t+2 t+3 Не то, что мы ожидали! 17 mov eax, [sum] add eax, 1 mov [sum], eax Прагмы синхронизации #pragma omp single – исполняет следующую команду только с помощью одного (случайного) потока #pragma omp barrier – удерживает потоки в этом месте, пока все потоки не дойдут дотуда #pragma omp atomic – атомарно исполняет следующую операцию доступа к памяти (т.е. без прерывания от других ветвей) #pragma omp critical [имя потока] – позволяет только одному потоку перейти к исполнению следующей команды int a[N], sum = 0; #pragma omp parallel for for (int i = 0; i < N; i++) { #pragma omp critical sum += a[i]; // one thread at a time } 18 Упражнение 5: синхронизация Для решения нашей проблемы синхронизации используйте нужную прагму синхронизации Скомпилируйте и запустите 19 Упражнение 6: профилирование Включите в компиляторе профилирование OpenMP™ /Qopenmp_profile Скомпилируйте снова Создайте проект Intel® Thread Profiler для PrimeHT.exe; примите все настройки по умолчанию Запустите Intel® VTune™ Performance Analyzer New Project | Threading Toolkit | Thread Analyzer Wizard; проверьте: Number of Threads = 2 Запустите сессию профилирования Посмотрите результат в видах Summary, Threads, Regions 20 omp for schedule: схемы schedule определяет, как шаги цикла приписываются разным потокам Компромисс между двумя противоположными целями: – Наилучший баланс загрузки потоков – Минимальное дополнительное время, потраченное на обработку цикла schedule(static) Один поток schedule(guided, f) schedule(dynamic, c) C N/2 N f 21 Упражнение 7: планирование Усовершенствуйте схему планирования Скомпилируйте и перепрофилируйте Добейтесь оптимальной загрузки потоков при минимальных дополнительных затратах на обработку цикла 22 Сведение Можно ли сделать лучше, чем синхронизировать все доступы к одному общему накопителю? Альтернатива: – Частный накопитель в каждом потоке – Для получения окончательного значения все частные накопители суммируются (сводятся к одному) в конце Операции сведения: +, *, -, &, ^, |, &&, || int a[N], sum = 0; #pragma omp parallel for reduction(+: sum) for (int i = 0; i < N; i++) { sum += a[i]; // no synchronization needed } 23 Упражнение 8: сведение Используйте прагму «reduction», чтобы избавиться от синхронизации и связанных с ней дополнительных задержек Скомпилируйте и спрофилируйте Подготовьте непрофилированную версию и проведите окончательные замеры Поздравляем! 24 Прагмы OpenMP™ на заметку Основная прагма, порождает группу потоков – omp parallel Прагмы, разделяющие задачу (можно объединять с прагмой parallel) – omp sections – omp for Клаузулы для прагм, разделяющий задачу – private, shared, reduction – область действия переменных – schedule – управление планированием Прагмы синхронизации – omp critical [имя потока] – omp barrier 25 Решение #pragma omp parallel for private(cand, max_div, div) \ reduction(+: counter, count31) \ schedule(guided, 10) for (cand = from; cand <= to; cand += 2) { prime = true; max_div = ((long)sqrt((double)cand)) + 1; ... Все что требуется для эффективного распараллеливания – добавить одну строчку в исходный код! 26 Что еще есть в OpenMP™? Другие способы определения областей действия переменных и их инициализации Более сложные прагмы синхронизации OpenMP™ API и переменные окружения – Контроль количества потоков – Ручная низкоуровневая синхронизация… Модель «очереди задач» для разделения задания – Расширение, специфичное для Intel и пока не стандартизованное Совместимость с Win32* и P-потоками www.openmp.org 27 «Очередь» для разделения задачи Для более сложных интерактивных моделей, не укладывающихся в рамки обычных циклов struct Node { int data; Node* next; }; Node* head; for (Node* p = head; p != NULL; p = p->next) { process(p->data); } Node* p; #pragma intel omp taskq shared(p) for (p = head; p != NULL; p = p->next) //only 1 thrd { #pragma intel omp task process(p->data); // queue task to be executed } // on any available thread 28 Итоги и выводы Технология Hyper-Threading повышает производительность процессора при очень низких затратах Технология HT доступна сегодня на массовых настольных ПК Для извлечения преимуществ технологии HT, разбивайте на потоки Ваше приложение! Используйте OpenMP™ для легкого поэтапного распараллеливания Вашего приложения! Для достижения максимальной производительности используйте Intel Threading Tools 29 Полезные ресурсы developer.intel.com/software/products/ compilers/ www.openmp.org Руководство Intel® Compiler User Guide 30 Спасибо за внимание! Пожалуйста, не забудьте developer.intel.com вернуть заполненные анкеты 31 Дополнительные материалы 32 Использование распараллеливания Уровень распараллел ивания Где используется Технология Команды Гиперконвейерные, сложные исполнительные устройства, предсказание ветвлений Микроарх. Intel Использование NetBurst® (гиперконвейерная, суперскалярная, спекулятивная) Данные SIMD MMX, SSE, SSE2 Область действия Задача, поток Несколько процессоров SMP Цена 33 Проблема Опции Intel® Compiler для многопоточности и OpenMP™ Автоматическое распараллеливание –/Qparallel Поддержка OpenMP™ –/Qopenmp –/Qopenmp_report{0|1|2} 34 Ключевые термины Многопроцессорность (MP) – аппаратная технология для повышения производительности за счет увеличения числа процессоров Технология Hyper-Threading (HT) – аппаратная технология для повышения производительности за счет более оптимального использования ресурсов процессора Многопоточность (MT) – программная технология для повышения функциональности и производительности ПО за счет использования нескольких (логических) процессоров 35 HT - технология, никакой мистики Несколько процессоров Арх. сост. Кэш-память Проц. Блок исполнения команд Арх. сост. Кэш-память Проц. Блок исполнения команд Hyper-Threading Арх. сост. Арх. сост. Кэш-память Проц. Блок исполнения команд Технология HT повышает производительность процессора благодаря лучшему использованию ресурсов 36 Технология HT: что внутри Буферы потоковых команд Instruction TLB Указатель следующей команды Return Stack Predictor Trace Cache Next IP Trace Cache Fill Buffers Таблицы псевдонимов регистров Технология HT повышает производительность процессора при минимальных затратах 37 HT: использование преимуществ HT прозрачна для ОС и приложений – ПО просто «видит» несколько процессоров Способы использования ПО для извлечения преимуществ от технологии HT: – Многопоточность – в пределах одного приложения – Многозадачность – среди нескольких приложений Поддержка со стороны ОС увеличивает преимущества технологии HT: – тонкое планирование с учетом логических процессоров – остановка логических процессоров в пустом цикле – внедрена в: Windows* XP, Linux* 2.4.x Для использования преимуществ технологии HT разбивайте Ваше приложение на несколько потоков! 38 Разбивайте Ваше приложение на несколько потоков Что? Стратегия многопоточности Как? Внедрение многопоточности 39 Распараллеливание задачи Разделите всю задачу на несколько несвязанных друг с другом задач Исполняйте эти задачи одновременно (отдельными потоками) Данные Поток сжатия Данные Data 40 Поток шифрования Данные Data Распараллеливание данных Разделите данные на несколько несвязанных друг с другом наборов Назначьте эти наборы одновременно исполняемым потокам Поток A … Поток N 41 Внедрение многопоточности API / Библиотека – Win32* API – P-потоки – MPI Языки программирования – Java* – C# Расширение языков программирования – OpenMP™ 42