ЛЕКЦИЯ 3. Стандарт POSIX Threads
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
Доклад Кулагина И.И., Пазникова А.А., Курносова М.Г. "Оптимизация информационных обменов в параллельных PGAS-программах" на 3-й Всероссийской научно-технической конференции «Суперкомпьютерные технологии» (СКТ-2014)
29 сентября – 4 октября 2014 г., с. Дивноморское
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...Alexey Paznikov
ЛЕКЦИЯ 2. POSIX Threads. Жизненный цикл потоков. Планирование. Синхронизация
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...Alexey Paznikov
ЛЕКЦИЯ 6. Атомарные операции. Внеочередное выполнение инструкций. Барьеры памяти. Семантика захвата-освобождения. Модель памяти C++
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...Alexey Paznikov
ЛЕКЦИЯ 7. Модель памяти С++. Атомарные операции. Внеочередное выполнение инструкций. Барьеры памяти. Семантика захвата-освобождения
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Лекция 1. Основные понятия стандарта MPI. Дифференцированные обменыAlexey Paznikov
ЛЕКЦИЯ 1. Основные понятия стандарта MPI. Дифференцированные обмены
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Причины потерь процессорного времени при организации последовательности вычислений внутри потока: 1. Ожидание ответа на запрос (поток спит). 2. Выполнение дополнительных "лишних" действий. Как способ устранения этих потерь - паттерн Пул потоков. Анализ императивного и функционального подхода к борьбе с "жадными" операциями. Эволюция методов организации параллельных вычислений на основе пула потоков.
В третьей главе рассматриваются базовые свойства акторов, описанные в PhD диссертации Gul Agha: каждый актор имеет адрес, большой почтовый ящик, куда доставляются сообщения, адресованные актору и поведение. В ответ на входящее сообщение актор может отправить конечный набор сообщений другим акторам и/или создать конечное число новых акторов и/или поменять свое поведение для обработки следующего сообщения.
В рамках данного курса будет разработана библиотека для разработки параллельных приложений на платформе .NET, построенная по модели акторов.
Исходные коды библиотеки будут выкладываться на GitHub: https://github.com/hwdtech/HWdTech.DS
Код библиотеки будет разработан с использованием следующих принципов, приемов и методик:
S.O.L.I.D. - принципы
Unit-tests
Mock
IoC контейнеры
Для удобства слушателей курса краткий обзор данных практик приведен в Главе 4.
Доклад Кулагина И.И., Пазникова А.А., Курносова М.Г. "Оптимизация информационных обменов в параллельных PGAS-программах" на 3-й Всероссийской научно-технической конференции «Суперкомпьютерные технологии» (СКТ-2014)
29 сентября – 4 октября 2014 г., с. Дивноморское
ПВТ - весна 2015 - Лекция 2. POSIX Threads. Основные понятия многопоточного п...Alexey Paznikov
ЛЕКЦИЯ 2. POSIX Threads. Жизненный цикл потоков. Планирование. Синхронизация
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ПВТ - осень 2014 - Лекция 6 - Атомарные операции. Внеочередное выполнение инс...Alexey Paznikov
ЛЕКЦИЯ 6. Атомарные операции. Внеочередное выполнение инструкций. Барьеры памяти. Семантика захвата-освобождения. Модель памяти C++
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
ПВТ - весна 2015 - Лекция 7. Модель памяти С++. Внеочередное выполнение инстр...Alexey Paznikov
ЛЕКЦИЯ 7. Модель памяти С++. Атомарные операции. Внеочередное выполнение инструкций. Барьеры памяти. Семантика захвата-освобождения
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Лекция 1. Основные понятия стандарта MPI. Дифференцированные обменыAlexey Paznikov
ЛЕКЦИЯ 1. Основные понятия стандарта MPI. Дифференцированные обмены
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Причины потерь процессорного времени при организации последовательности вычислений внутри потока: 1. Ожидание ответа на запрос (поток спит). 2. Выполнение дополнительных "лишних" действий. Как способ устранения этих потерь - паттерн Пул потоков. Анализ императивного и функционального подхода к борьбе с "жадными" операциями. Эволюция методов организации параллельных вычислений на основе пула потоков.
В третьей главе рассматриваются базовые свойства акторов, описанные в PhD диссертации Gul Agha: каждый актор имеет адрес, большой почтовый ящик, куда доставляются сообщения, адресованные актору и поведение. В ответ на входящее сообщение актор может отправить конечный набор сообщений другим акторам и/или создать конечное число новых акторов и/или поменять свое поведение для обработки следующего сообщения.
В рамках данного курса будет разработана библиотека для разработки параллельных приложений на платформе .NET, построенная по модели акторов.
Исходные коды библиотеки будут выкладываться на GitHub: https://github.com/hwdtech/HWdTech.DS
Код библиотеки будет разработан с использованием следующих принципов, приемов и методик:
S.O.L.I.D. - принципы
Unit-tests
Mock
IoC контейнеры
Для удобства слушателей курса краткий обзор данных практик приведен в Главе 4.
ЛЕКЦИЯ 4. Стандарт POSIX Threads. Реентерабельность функций. Обработка сигналов. Локальные данные потоков. Принудительное завершение потоков. Шаблоны программирования с использованием потоков
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
Зачастую, знакомство с алиасингом в C++ у многих программистов начинается и заканчивается одинаково: -fno-strict-aliasing. На вопросы новичка, более опытные коллеги отвечают в стиле: «не трогай! а то все сломаешь!». Новичок и не трогает. В докладе будет предпринята попытка заглянуть под капот и понять, что же там, внутри. Что такое алиасинг, где он может быть полезен и какие реальные преимущества дает. Тема будет рассмотрена и со стороны программиста и со стороны разработчика компилятора. А по сему, вопрос «зачем?» будет центральным в повествовании.
ЛЕКЦИЯ 4. Шаблоны многопоточного программирования
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Модель памяти C++ - Андрей Янковский, ЯндексYandex
В докладе Андрей расскажет о моделях памяти различных процессоров, о тонкостях реализации неблокирующих алгоритмов и о том, какое отношение всё это имеет к С++.
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...Alexey Paznikov
ЛЕКЦИЯ 6. Разработка параллельных структур данных на основе блокировок
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Sergey Platonov
В последнее время в промышленной разработке ПО особую популярность обретают Domain-Specific Lanugages (DSL). Они драматически упрощают разработку и дают возможность “программировать” не только программистам, но и пользователям прикладных программ.
В своем докладе я расскажу об опыте использования DSL применительно к С++, причем упор будет сделан на производительность кода DSL, и его мгновенную “встраиваемость” в запущенную программу путем компиляции DSL-кода в нативный код с помощью инструментария LLVM.
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Alexey Paznikov
ЛЕКЦИЯ 2. Коллективные операции в стандарте MPI
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Применение фреймворка GStreamer в системе видеонаблюденияcorehard_by
Я хочу рассказать о фреймворке GStreamer, который предназначен для обработки аудио/видеоданных. А также для чего мы его использовали в одном из наших проектов.
Как показывает практика, повсеместное применение классического, основанного на callback’ах подхода к асинхронному программированию обычно оказывается неудобным. Для упрощения написания и поддержки сложного асинхронного кода можно использовать иной подход — с использованием сопрограмм. Он значительно сокращает объём и сложность кода, превращая код из асинхронного в синхронный.
Иван Пузыревский — Введение в асинхронное программированиеYandex
Доклад посвящен основам асинхронного программирования. Мы кратко обсудим историю вопроса: что такое асинхронность, где, почему и зачем она используется. Затем рассмотрим наиболее частые способы построения асинхронных интерфейсов: основанные на callback'ах и на future/promise. В ходе доклада выделим основные используемые концепции, посмотрим на их реализацию и примеры использования. А в конце поговорим о сложностях, которые часто встречаются в асинхронном программировании.
ЛЕКЦИЯ 4. Стандарт POSIX Threads. Реентерабельность функций. Обработка сигналов. Локальные данные потоков. Принудительное завершение потоков. Шаблоны программирования с использованием потоков
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
Зачастую, знакомство с алиасингом в C++ у многих программистов начинается и заканчивается одинаково: -fno-strict-aliasing. На вопросы новичка, более опытные коллеги отвечают в стиле: «не трогай! а то все сломаешь!». Новичок и не трогает. В докладе будет предпринята попытка заглянуть под капот и понять, что же там, внутри. Что такое алиасинг, где он может быть полезен и какие реальные преимущества дает. Тема будет рассмотрена и со стороны программиста и со стороны разработчика компилятора. А по сему, вопрос «зачем?» будет центральным в повествовании.
ЛЕКЦИЯ 4. Шаблоны многопоточного программирования
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Модель памяти C++ - Андрей Янковский, ЯндексYandex
В докладе Андрей расскажет о моделях памяти различных процессоров, о тонкостях реализации неблокирующих алгоритмов и о том, какое отношение всё это имеет к С++.
ПВТ - весна 2015 - Лекция 6. Разработка параллельных структур данных на основ...Alexey Paznikov
ЛЕКЦИЯ 6. Разработка параллельных структур данных на основе блокировок
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Юрий Ефимочев, Компилируемые в реальном времени DSL для С++ Sergey Platonov
В последнее время в промышленной разработке ПО особую популярность обретают Domain-Specific Lanugages (DSL). Они драматически упрощают разработку и дают возможность “программировать” не только программистам, но и пользователям прикладных программ.
В своем докладе я расскажу об опыте использования DSL применительно к С++, причем упор будет сделан на производительность кода DSL, и его мгновенную “встраиваемость” в запущенную программу путем компиляции DSL-кода в нативный код с помощью инструментария LLVM.
Лекция 2. Коллективные операции в MPI. Параллельные алгоритмы случайного блуж...Alexey Paznikov
ЛЕКЦИЯ 2. Коллективные операции в стандарте MPI
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Применение фреймворка GStreamer в системе видеонаблюденияcorehard_by
Я хочу рассказать о фреймворке GStreamer, который предназначен для обработки аудио/видеоданных. А также для чего мы его использовали в одном из наших проектов.
Как показывает практика, повсеместное применение классического, основанного на callback’ах подхода к асинхронному программированию обычно оказывается неудобным. Для упрощения написания и поддержки сложного асинхронного кода можно использовать иной подход — с использованием сопрограмм. Он значительно сокращает объём и сложность кода, превращая код из асинхронного в синхронный.
Иван Пузыревский — Введение в асинхронное программированиеYandex
Доклад посвящен основам асинхронного программирования. Мы кратко обсудим историю вопроса: что такое асинхронность, где, почему и зачем она используется. Затем рассмотрим наиболее частые способы построения асинхронных интерфейсов: основанные на callback'ах и на future/promise. В ходе доклада выделим основные используемые концепции, посмотрим на их реализацию и примеры использования. А в конце поговорим о сложностях, которые часто встречаются в асинхронном программировании.
Модули threading, queue и concurrent.futures. Использование потоков для параллельных вычислений на Python. GIL. Параллельность и конкурентность. Модуль asyncio. Модуль multiprocessing.
ЛЕКЦИЯ 3. Реентерабельность. Сигналы. Локальные данные потоков. Принудительное завершение потоков
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
Казалось, закончились долгие обсуждения в форумах, как измерить время работы алгоритма, какие функции использовать, какую точность ожидать. Жаль, но опять придется вернуться к этому вопросу. На повестке дня вопрос – как лучше измерить скорость работы параллельного алгоритма.
разработка серверов и серверных приложений лекция №3etyumentcev
В третьей главе рассматриваются базовые свойства акторов, описанные в PhD диссертации Gul Agha: каждый актор имеет адрес, большой почтовый ящик, куда доставляются сообщения, адресованные актору и поведение. В ответ на входящее сообщение актор может отправить конечный набор сообщений другим акторам и/или создать конечное число новых акторов и/или поменять свое поведение для обработки следующего сообщения.
В рамках данного курса будет разработана библиотека для разработки параллельных приложений на платформе .NET, построенная по модели акторов.
Исходные коды библиотеки будут выкладываться на GitHub: https://github.com/hwdtech/HWdTech.DS
Код библиотеки будет разработан с использованием следующих принципов, приемов и методик:
S.O.L.I.D. - принципы
Unit-tests
Mock
IoC контейнеры
Для удобства слушателей курса краткий обзор данных практик приведен в Главе 4.
разработка серверов и серверных приложений лекция №2etyumentcev
Причины потерь процессорного времени при организации последовательности вычислений внутри потока: 1. Ожидание ответа на запрос (поток спит). 2. Выполнение дополнительных "лишних" действий. Как способ устранения этих потерь - паттерн Пул потоков. Анализ императивного и функционального подхода к борьбе с "жадными" операциями. Эволюция методов организации параллельных вычислений на основе пула потоков.
Григорий Демченко — Асинхронное программирование и сопрограммыYandex
Как показывает практика, повсеместное применение классического, основанного на callback’ах подхода к асинхронному программированию обычно оказывается неудобным. Для упрощения написания и поддержки сложного асинхронного кода можно использовать иной подход — с использованием сопрограмм. Он значительно сокращает объём и сложность кода, а также существенно упрощает реализацию нетривиальных сценариев, связанных с отменой вычислений и таймаутами операций.
Павел Сушин «Асинхронное программирование на С++: callbacks, futures, fibers»Platonov Sergey
За время работы над проектом был разработан удобный фреймворк для написания асинхронного кода. В докладе будет рассмотрено то, как он устроен и как со временем эволюционировал. Разберемся, как с помощью наших примитивов решать проблемы, часто встречающиеся в асинхронном программирование; будут примеры удачного и неудачного использования. Отдельно остановимся на сравнении получившихся средств с тем, что было добавлено в С++11.
ЛЕКЦИЯ 6. Параллельная сортировка. Алгоритмы комбинаторного поиска. Параллельный ввод-вывод в MPI
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Лекция 5. Метод конечных разностей (параллельные алгоритмы в стандарте MPI)Alexey Paznikov
ЛЕКЦИЯ 5. Метод конечных разностей (параллельные алгоритмы в стандарте MPI)
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Лекция 4. Производные типы данных в стандарте MPIAlexey Paznikov
ЛЕКЦИЯ 4. Производные типы данных в стандарте MPI
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
Лекция 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI...Alexey Paznikov
ЛЕКЦИЯ 3. Виртуальные топологии в MPI. Параллельные алгоритмы в стандарте MPI умножения матрицы на вектор, метода Монте-Карло, решение линейных алгебраических уравнений (СЛАУ) методами Гаусса и сопряжённых градиентов
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
http://cpct.sibsutis.ru/~apaznikov/teaching
ЛЕКЦИЯ 8. Многопоточное программирование без использования блокировок. Модель потребитель-производитель. Потокобезопасный стек. Проблема ABA. Указатели опасности.
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ЛЕКЦИЯ 5. Шаблоны многопоточного программирования
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ЛЕКЦИЯ 1. Актуальность параллельных вычислений. Анализ параллельных алгоритмов. Многоядерные вычислительные систем с общей памятью
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ЛЕКЦИЯ 0. Описание курса. Общие вопросы, структура курса, требования. Содержание курса. Полезные ресурсы
Курс "Параллельные вычислительные технологии" (ПВТ), весна 2015
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ЛЕКЦИЯ 7. Многопоточное программирование без блокировок. Модель потребитель-производитель. Потокобезопасный стек: проблема ABA, указатели опасности, сборщики мусора, счётчик ссылок, применение модели памяти С++.
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
http://cpct.sibsutis.ru/~apaznikov
ПВТ - осень 2014 - Лекция 5 - Многопоточное программирование в языке С++. Р...Alexey Paznikov
ЛЕКЦИЯ 5. Многопоточное программирование в языке С++. Работа с потоками. Защита данных. Синхронизация. Будущие результаты
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
ПВТ - осень 2014 - Лекция 2 - Архитектура вычислительных систем с общей памятьюAlexey Paznikov
ЛЕКЦИЯ 2. Архитектура вычислительных систем с общей памятью
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
ЛЕКЦИЯ 1. Введение в параллельные вычисления
Курс "Параллельные вычислительные технологии" (ПВТ), осень 2014
Сибирский государственный университет телекоммуникаций и информатики
преподаватель:
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных систем СибГУТИ
ЛЕКЦИЯ 1а. Описание курса "Параллельные вычислительные технологии" (ПВТ), осень 2014
Пазников Алексей Александрович
к.т.н., доцент кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
ЛЕКЦИЯ 11. Технико-экономическая эффективность функционирования вычислительных систем
Пазников Алексей Александрович
к.т.н., ст. преп. Кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
ЛЕКЦИЯ 10. Осуществимость решения задач на вычислительных системах
Пазников Алексей Александрович
к.т.н., ст. преп. Кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
ЛЕКЦИЯ 9. Показатели структурной живучести распределённых ВС
Пазников Алексей Александрович
к.т.н., ст. преп. Кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
ЛЕКЦИЯ 8. Расчёт функций потенциальной живучести распределённых вычислительных систем
Пазников Алексей Александрович
к.т.н., ст. преп. Кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
ЛЕКЦИЯ 7. Методика расчета показателей живучести ВС. Континуальный подход к анализу живучести большемасштабных ВС.
Пазников Алексей Александрович
к.т.н., ст. преп. Кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
ЛЕКЦИЯ 5. Живучие ВС. Потенциальная и структурная живучесть ВС. Показатели потенциальной живучести ВС
Пазников Алексей Александрович
к.т.н., ст. преп. Кафедры вычислительных системСибирский государственный университеттелекоммуникаций и информатики
4. ▪ POSIX: Portable Operating Systems Interface
for uniX
▪ Стандартный API для работы с потоками в
UNIX-подобных системах с 1995 г.
(IEEE/ANSI 1003.1c-1995)
▪ Низкоуровневый интерфейс для
многопоточного программирования в среде
C/UNIX
▪ Основа для других высокоуровных моделей
(C++11-threads, OpenMP, Java threads, etc)
5. ˝˿˵˶˼̍SWKUHDGV
▪ Модель fork-join: потоки могут порождать (spawn,
start) другие потоки и ждать их завершения.
▪ Выполнение потоков планируется ОС, они могут
выполняться последовательно или
параллельно, могут назначаться на
произвольные ядра.
▪ Потоки работают независимо, асинхронно.
▪ Для координации доступа должны использоваться
механизмы (мьютексы, условные переменные и
др.) взаимного исключения
7. ˝˿˵˶˼̍SWKUHDGV
Поток а
(основной)
Поток b
Поток c
Поток d
spawn
Поток e
spawn
spawn
spawn
join
join
join
join
8. ˛˱˻˹̂̀˿˼̍˸˿˳˱̃̍
▪ Подключить заголовочный файл pthread.h
▪ Все функции начинаются с префикса pthread_
▪ Проверять код ошибки (if (rc != 0) { … })
▪ Компилировать
gcc -Wall -pedantic -O3 -pthread
-o prog prog.c
9. ˠ˿́˿˷˵˶˾˹˶̀˿̃˿˻˱
int pthread_create(pthread_t *tid,
const pthread_attr_t *attr,
void *(*start_routine) (void *) fun,
void *arg);
tid - идентификатор потока (для завершения,
синхронизации и т.д.)
attr - параметры потока (например, минимальный
размер стека)
fun - функция для запуска (принимает и возвращает
указатель void*)
arg - аргументы функции
32. ˨˶˽˽˿˷˶̃˲̌̃̍˳̌˸˳˱˾˱˱˻̃˹˳˱̇˹̐̀˿̃˿˻˱
1. Синхронизация (synchronization). T1 запрашивает
мьютекс, и если он занят потоком T2, то Т1 встаёт в
очередь, тем самым давая возможность другим потокам
запуститься.
2. Вытеснение (preemption). Происходит событие, в
результате которого высокоприоритетный поток Т2 может
запуститься. Тогда поток Т1 с низким приоритетом
вытесняется, и Т2 запускается.
3. Уступание (yielding). Программист явно вызывает
sched_yield() во время работы Т1, и тогда планировщик
ищет другой поток Т2, который может запуститься, и
запускает его.
4. Квантование (time-slicing). Квант времени для потока Т1
истёк. Тогда поток Т2 получает квант и запускается.
33. ˢ˿̂̃˿̐˾˹̐̀˿̃˿˻˱
1. Активный (active). Выполняется на
процессоре.
2. Готов запуститься (runnable).
Может и хочет запуститься, но пока
нет ресурсов.
3. Сон (sleeping). Ождиает изменения
состояния переменной синхронизации.
4. Зомби (zombie). Поток закончил своё
выполнение и ждёт, когда его ресурсы
заберут.
Sync.
Variabe
35. ˠ́˹˽˶́̀˼˱˾˹́˿˳˱˾˹̐̀˿̃˿˻˿˳
T1 T2 T3
lock
unlock
lock
Held 1
Sleepers ⚫
Time
0
lock
unlock
1 lock
T2 ⚫
Held 1
Sleepers ⚫
lock
unlock
2 lock Held 0
Sleepers ⚫
lock
unlock
3 lock Held 1
Sleepers ⚫
SIG
36. ˠ́˹˽˶́̀˼˱˾˹́˿˳˱˾˹̐̀˿̃˿˻˿˳
T1 T2 T3
lock
unlock
lock
Held 1
Sleepers ⚫
Time
0
lock
unlock
1 lock
T2 ⚫
Held 1
Sleepers ⚫
lock
unlock
2 lock Held 0
Sleepers ⚫
lock
unlock
3 lock Held 1
Sleepers ⚫
SIG
pthread_mutex_lock();
/* критическая секция */
pthread_mutex_unlock()
lock
unlock
37. ˠ́˹˽˶́̀˼˱˾˹́˿˳˱˾˹̐̀˿̃˿˻˿˳
T1 T2 T3
lock
unlock
lock
Held 1
Sleepers ⚫
Time
0
lock
unlock
1 lock
T2 ⚫
Held 1
Sleepers ⚫
lock
unlock
2 lock Held 0
Sleepers ⚫
lock
unlock
3 lock Held 1
Sleepers ⚫
SIG
38. ˛˱˻˸˱˵˱̃̍̀˿˼˹̃˹˻̄̀˼˱˾˹́˿˳˱˾˹̐˳SWKUHDG
int pthread_setschedparam(pthread_t thread,
struct sched_param {
int sched_priority;
};
int policy,
const struct sched_param *param);
int pthread_getschedparam(pthread_t thread,
int *policy,
struct sched_param *param);
Normal policies:
● SCHED_OTHER
● SCHED_BATCH
● SCHED_IDLE
Real-time policies:
● SCHED_FIFO
● SCHED_RR
● SCHED_DEADLINE
0
1..99
39. ˞˿́˽˱˼̍˾˿˶̀˼˱˾˹́˿˳˱˾˹˶6+('B27+(5
SCHED_OTHER
● Планирование с разделением времени по
умолчанию в Linux.
● Используется динамический приоритет,
основанный на значении nice value (nice,
setpriority, sched_setattr), которое повышается
каждый раз, когда поток может запуститься
(runnable), но откладывается планировщиком.
● Обеспечивает справедливое (fair) планирование.
40. ˞˿́˽˱˼̍˾˿˶̀˼˱˾˹́˿˳˱˾˹˶6+('B%$7+
SCHED_BATCH (начиная с 2.6.16)
● Похоже на SCHED_OTHER (планирует потоки в
соответствии с динамическим приоритетом)
● Планировщик всегда предполагает, что поток
требователен к ресурсу процессора (CPU-intensive).
● Планировщик назначает штрафы (penalty) на
активацию потока.
● Для неинтерактивных задач, выполняющих большой
объем вычислений без уменьшение значения nice или
● В задачах, для которых требуется детерминированное
поведение при планировании (пакетная обработка
задач - batch processing).
44. 5HDOWLPH̀˿˼˹̃˹˻˹̀˼˱˾˹́˿˳˱˾˹̐6+('B'($'/,1(
SCHED_DEADLINE (начиная с 3.14)
● Спорадическая модель планирования.
● Основан на алгоритмах GEDF (Global Earliest Deadline
First) и CBS (Constant Bandwidth Server)
● Спорадическое пакет задач (sporadic task) -
последовательность задач, где каждая задача
запускается не более 1 раза за период.
● Каждая задача также имеет относительный дедлайн
(relative deadline), до которого она должна
завершиться, и время вычислений, в течение
которого она будет занимать процессор.
45. 5HDOWLPH̀˿˼˹̃˹˻˹̀˼˱˾˹́˿˳˱˾˹̐6+('B'($'/,1(
SCHED_DEADLINE (начиная с 3.14)
● Момент, когда пакет задач должен начаться
выполняться из-за того, что пришла новая задача,
называется время поступления.
● Время начала выполнения - это время, когда пакет
начинает выполняться.
● Абсолютный дедлайн = относительный дедлайн +
время поступления.
47. 5HDOWLPH̀˿˼˹̃˹˻˹̀˼˱˾˹́˿˳˱˾˹̐6+('B'($'/,1(
время начала
абсолютный дедлайн
время выполнения T1
время поступления
sched_runtime
дедлайн (sched_deadline)
период (sched_period)
▪ CBS гарантирует невмешательствуо пакетов между собой путём
остановки потоков, которые пытаются выполняться больше
отведённого им времени (runtime)
▪ Ядро предотвращает ситуации, когда нельзя выполнить
планирование потоков с политикой SCHED_DEADLINE
(например, проверяется, достаточно ли будет имеющихся
процессоров)
▪ Потоки с политикой SCHED_DEADLINE имеют
наивысший приоритет! (среди всех других политик)
48. ˠ́˱˳˹˼˱˹̂̀˿˼̍˸˿˳˱˾˹̐UHDOWLPH̀˿˼˹̃˹˻̀˼˱˾˹́˿˳˱˾˹̐
▪ По возможности, никогда не использовать real-time
политики.
▪ Если вам требуется полное внимание
пользователя на чём-то постоянно
изменяющемся (движение курсора, поток
видео или аудио)
▪ Осуществление обратной связи и контроль
(управление машинами, роботами)
▪ Сбор и обработка статистики в реальном
времени.
49. ˢ˿˳˶̃̌
▪ Оптимизируйте работу кэша
▫ Переключения контекста вызывают
копирование кэша - это очень долго.
▫ Используйте привязку выполнения потоков
к ядрам процессора (processor affinity).
▪ Если вы много думаете об планировании -
вероятно, вы делаете что-то не так.
51. ˠ́˿˲˼˶˽˱̂˹˾̆́˿˾˹˸˱̇˹˹˹˱̃˿˽˱́˾̌˶˿̀˶́˱̇˹˹
Поток A: i = i + 1
Записать значение
переменной i в регистр
(регистр = 5)
t
Увеличить содержимое
регистра (регистр = 6)
Сохранить значение
регистра в перменную i
(регистр = 6)
Поток B: i = i + 1
Записать значение
переменной i в регистр
(регистр = 5)
Увеличить содержимое
регистра (регистр = 6)
Сохранить значение
регистра в перменную i
(регистр = 6)
i
5
5
6
6
52. ˠ́˿˲˼˶˽˱̂˹˾̆́˿˾˹˸˱̇˹˹˹˱̃˿˽˱́˾̌˶˿̀˶́˱̇˹˹
Поток 1 Поток 2
bal = GetBalance(account);
bal += bal * InterestRate;
PutBalance(account, bal);
bal = GetBalance(account);
bal += deposit;
PutBalance(account, bal);
● Критическая секция - участок кода, доступ к которого
должен обеспечиваться полностью без прерываний.
● ВСЕ общие данные должны быть защищены.
● Общие данные - те, к которым могут иметь доступ
несколько потоков (глобальные, статические
переменные и др.).
53. ˠ́˿˲˼˶˽˱̂˹˾̆́˿˾˹˸˱̇˹˹˹˱̃˿˽˱́˾̌˶˿̀˶́˱̇˹˹
Поток 1 Поток 2
bal = GetBalance(account);
bal += bal * InterestRate;
PutBalance(account, bal);
bal = GetBalance(account);
bal += deposit;
PutBalance(account, bal);
Реализация синхронизация требует аппаратной поддержки
атомарной операции test and set (проверить и установить).
test_and_set(address)
{
result = Memory[address]
Memory[address] = 1
return result;
}
Установить новое значение
(обычно 1) в ячейку и
возвратить старое
значение.
54. ˠ́˿̂̃˶˺̉˱̐́˶˱˼˹˸˱̇˹̐˳˸˱˹˽˾˿˴˿˹̂˻˼̏̈˶˾˹̐
// инициализация (к моменту вызова CriticalSection
// не гарантируется, что skip == false)
skip = false
function CriticalSection() {
while test_and_set(lock) = true
skip // ждать, пока не получится захватить
// только один поток может быть в критической секции
critical section
// освободить критическую секцию
lock = false
}
55. ˠ́˿̂̃˶˺̉˱̐́˶˱˼˹˸˱̇˹̐˳˸˱˹˽˾˿˴˿˹̂˻˼̏̈˶˾˹̐
enter_region: ; Начало функции
tsl reg, flag ; Выполнить test_and_set.
; flag - разделяемая переменная,
; которая копируется в регистр
; и затем устанавливается в 1.
cmp reg, #0 ; Был flag равен 0 в entry_region?
jnz enter_region ; Перейти на начало, если reg ≠ 0
; то есть flag ≠ 0 на входе
ret ; Выход. Флаг был равен 0 на входе.
; Если достигли этой точки, значит
; мы внутри критической секции!
leave_region:
move flag, #0 ; записать 0 во флаг
ret ; вернуться в вызывающую функцию
56. ˝̍̏̃˶˻̂̌
/* инициализация мьютекса */
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
/* или */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* уничтожение мьютекса (освобождение ресурсов) */
int pthread_mutex_destroy(pthread_mutex_t *mutex);
/* заблокировать мьютекс */
int pthread_mutex_lock(pthread_mutex_t *mutex);
/* заблокировать мьютекс и не ожидать разблокировки */
int pthread_mutex_trylock(pthread_mutex_t *mutex);
/* разблокировать мьютекс */
int pthread_mutex_unlock(pthread_mutex_t *mutex);
57. ˝̍̏̃˶˻̂̌
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
T1
Priority:0
T2
Priority:1
T3
Priority:2
Held 1
Sleepers ⚫ T3 ⚫
T2 ⚫
lock
lock lock
68. ● Поток пытается дважды захватить один и тот же мьютекс
● Два мьютекса. Один поток удерживает первый мьютекс и
пытается запереть второй мьютекс, в то время как второй
поток удерживает второй мьютекс и пытается запереть
первый мьютекс.
T1 T2
А B
B А
70. ˠ́˹˽˶́́˱˲˿̃̌˵˳̄̆˽̍̏̃˶˻̂˿˳
int hash_func(fp) { }
pthread_mutex_t hashlock = PTHREAD_MUTEX_INITIALIZER;
struct elem *ht[SIZE];
struct elem {
int count;
pthread_mutex_t lock;
struct elem *next;
int id;
/* … */
}
71. ˠ́˹˽˶́́˱˲˿̃̌˵˳̄̆˽̍̏̃˶˻̂˿˳
/* добавить новый объект */
struct elem *elem_alloc(void) {
struct elem *ep;
int idx;
if ((ep = malloc(sizeof(struct elem))) != NULL) {
ep-count = 1;
if (pthread_mutex_init(fp-lock, NULL) != 0) {
free(ep);
return NULL;
}
idx = hash_func(ep);
pthread_mutex_lock(hashlock);
ep-next = ht[idx];
ht[idx] = ep-next;
pthread_mutex_lock(ep-lock);
pthread_mutex_unlock(hashlock);
/* продолжение инициализации */
pthread_mutex_unlock(fp-lock);
}
return ep;
}
72. ˠ́˹˽˶́́˱˲˿̃̌˵˳̄̆˽̍̏̃˶˻̂˿˳
/* добавить ссылку на объект */
void add_reference(struct elem *ep) {
pthread_mutex_lock(ep-lock);
ep-count++;
pthread_mutex_unlock(ep-lock);
}
/* найти существующий объект */
struct elem *find_elem(int id) {
struct elem *ep;
int idx;
idx = hash_func(ep);
pthread_mutex_lock(hashlock);
for (ep = ht[idx]; ep != NULL; ep = ep-next) {
if (ep-id == id) {
add_reference(ep); break;
}
}
pthread_mutex_unlock(hashlock);
return ep;
}
73. ˠ́˹˽˶́́˱˲˿̃̌˵˳̄̆˽̍̏̃˶˻̂˿˳
void elem_release(struct elem *ep) { /* осободить ссылку на объект */
int idx;
pthread_mutex_lock(ep-lock);
if (ep-count == 1) { /* последняя ссылка */
pthread_mutex_unlock(ep-lock);
pthread_mutex_lock(hashlock);
pthread_mutex_lock(ep-lock);
/* необходима повторная проверка условия */
if (ep-count != 1) {
ep-count--;
pthread_mutex_unlock(ep-lock);
pthread_mutex_unlock(hashlock);
return;
}
/* … найти и удалить из списка … */
pthread_mutex_unlock(ep-lock);
pthread_mutex_unlock(hashlock);
pthread_mutex_destroy(ep-lock);
} else {
ep-count--; pthread_mutex_unlock(ep-lock);
}
}
74. ˠ́˹˽˶́́˱˲˿̃̌˵˳̄̆˽̍̏̃˶˻̂˿˳̄̀́˿̊˶˾˹˶
void elem_release(struct elem *ep) { /* осободить ссылку на объект */
int idx;
pthread_mutex_lock(hashlock);
if (--ep-count == 0) { /* последняя ссылка */
pthread_mutex_unlock(ep-lock);
pthread_mutex_lock(hashlock);
pthread_mutex_lock(ep-lock);
/* необходима повторная проверка условия */
if (ep-count != 1) {
ep-count--;
pthread_mutex_unlock(ep-lock);
pthread_mutex_unlock(hashlock);
return;
}
/* … найти и удалить из списка … */
pthread_mutex_unlock(ep-lock);
pthread_mutex_unlock(hashlock);
pthread_mutex_destroy(ep-lock);
} else {
ep-count--; pthread_mutex_unlock(ep-lock);
}
}
75. ˓̌˲˿́˻́˹̃˹̈˶̂˻˹̆̂˶˻̇˹˺
При разработке многопоточных программ необходимо
учитывать балланс между эффективностью
блокировки и её сложностью, которые определяются
детализацией (“зернистостью”) критической секции.
● Грубая детализация (coarse-grained) критических
секций - низкая эффективность, но простота
разработки и поддержания кода.
● Мелкая детализация (fine-grained) критических
секция - высокая эффективность (которая может
снизиться из-за избыточного количества критических
секций), но сложность кода
77. ˒˼˿˻˹́˿˳˻˱̈̃˶˾˹̐˸˱̀˹̂˹
/* инициализация мьютекса */
int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock,
const pthread_rwlockattr_t *restrict attr);
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
/* особождение ресурсов, уничтожение мьютекса */
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
/* захватить мьютекс на чтение */
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
/* захватить мьютекс на запись */
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
/* освободить мьютекс */
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
87. ˡ˶˻̄́̂˹˳˾̌˶˽̍̏̃˶˻̂̌
▪ Рекурсивный мьютекс позволяет одному и тому же
потоку многократно запирать мьютекс, не отпирая его.
▪ Мьютекс освобождается тогда, когда количество
отпираний совпадает с количеством запираний.
int pthread_mutexattr_getpshared(const pthread_mutexattr_t
*restrict attr,
int *restrict pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);
pshared:
▫ PTHREAD_MUTEX_NORMAL - стандартный мьютекс, не производит
дополнительную проверку на наличие ошибок
▫ PTHREAD_MUTEX_ERRORCHECK - мьютекс, которые выполняет проверку на
наличие ошибок
▫ PTHREAD_MUTEX_RECURSIVE - рекурсивный мьютекс
90. ˠ́˿˲˼˶˽˱˙˾˳˶́̂˹̐̀́˹˿́˹̃˶̃˿˳
Поток Т1 с низким приоритетом удерживает мьютекс, который
необходим Т2 с высоким приоритетом. Во время удержания поток Т1
вытесняется потоком Т3 со средним приоритетом. В результате
поток Т2 зависит от освобождения мьютекса потоком Т1.
T1
Prior: 0
Runnable
T2
Prior: 2
Sleep
T3
Prior: 1
Active
lock(M1)
lock(M1)
unlock(M1)
T2 ⚫
Held 1
Sleepers ⚫
91. ˠ́˿˲˼˶˽˱˙˾˳˶́̂˹̐̀́˹˿́˹̃˶̃˿˳ˡ˶̉˶˾˹̐
■ Priority Ceiling Mutex
Устанавливается максимальный приоритет для потока, который захватывает
мьютекс. Каждый поток, который захватывает мьютек, автоматически
получает этот приоритет (даже если у него был ниже).
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t
*restrict attr, int *restrict prioceiling);
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr,
int prioceiling);
int pthread_mutex_getprioceiling(const pthread_mutex_t *restrict mutex,
int *restrict prioceiling);
int pthread_mutex_setprioceiling(pthread_mutex_t *restrict mutex,
int prioceiling, int *restrict old_ceiling);
■ Priority Inheritance Mutexes
Поток Т1 захватывает мьютекс без изменения своего приоритета. Когда
второй поток Т2 пытается захватить, владелец Т1 мьютекса получает
приоритет потока Т2.
92. ˠ́˿˲˼˶˽˱ˠ˿̂˼˶˵˿˳˱̃˶˼̍˾̌˺˸˱̆˳˱̃
▪ Потоки Т1 и Т2 используют мьютекс М1 для работы,
удерживая его значительное время. При этом основую
часть работы они выполняют в критической секции.
▪ Допустим Т1 захватывает М1. Т2, попытавшись захватить
мьютекс, засыпает. Тогда, после того, как Т1 освободит
мьютекс, он может успеть снова его захватить до того, как
проснётся Т1.
T1
работа
ожидание
запереть
(попытаться) отпереть
критическая секция
пробуждение
T2
Обычный случай
93. ˠ́˿˲˼˶˽˱ˠ˿̂˼˶˵˿˳˱̃˶˼̍˾̌˺˸˱̆˳˱̃
▪ Потоки Т1 и Т2 используют мьютекс М1 для работы,
удерживая его значительное время. При этом основую
часть работы они выполняют в критической секции.
▪ Допустим Т1 захватывает М1. Т2, попытавшись захватить
мьютекс, засыпает. Тогда, после того, как Т1 освободит
мьютекс, он может успеть снова его захватить до того, как
проснётся Т1.
T1
работа
ожидание
запереть
(попытаться) отпереть
критическая секция
пробуждение
T2
Т1 повторно захватывает мьютекс
94. ˠ́˿˲˼˶˽˱ˠ˿̂˼˶˵˿˳˱̃˶˼̍˾̌˺˸˱̆˳˱̃ˡ˶̉˶˾˹˶
Решение - использование FIFO-мьютекса: владелец
мьютекса (Т1) после освобождения мьютекса
автоматически передаёт права на захват мьютекса
первому потоку в очереди, который ожидает освобождения
мьютекса.
T1
работа
ожидание
запереть
(попытаться) отпереть
критическая секция
пробуждение
T2
Использование FIFO-мьютекса
96. ▪ Ограничивает число потоков, которые могут
зайти в заданный участок кода.
▪ Семафор - это счетчик s = 0, …, ∞
▪ Операции:
▫ sem_post - увеличивает значение семафора
▫ sem_wait - пытается уменьшить значение
семафора (и это удаётся сделать,
если s 0).
▫ sem_getvalue - вернуть текущее значение
семафора (используется редко)
98. ˳SWKUHDGV
/* проинициализировать семафор */
int sem_init(sem_t *sem, int pshared,
unsigned int value);
/* уничтожить семафор */
int sem_destroy(sem_t *sem);
/* уменьшить семафор на 1
* (заблокировать единицу ресурса) */
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem,
const struct timespec *abs_timeout);
/* увеличить семафор на 1
* (разблокировать единицу ресурса) */
int sem_post(sem_t *sem);
103. ˢ˶˽˱̅˿́̌ˠ́˹˽˶́̀́˿˹˸˳˿˵˹̃˶˼̍̀˿̃́˶˲˹̃˶˼̍
/* безопасная версия sem_wait, учитывающая
* прерывания во время выполнения sem_wait */
void _sem_wait(sem_t *sem)
{
while (sem_wait(sem) != 0) { }
}
/* получить по сети запрос и выделить под него память */
request_t *get_request()
{
request_t *request;
request_t = (request*) malloc(sizeof(request_t));
request-data = read_from_net();
return request;
}
106. ˠ́˿˹˸˳˿˵˹̃˶˼̍̀˿̃́˶˲˹̃˶˼̍̂˿˴́˱˾˹̈˶˾˹˶˽˵˼˹˾̌˿̈˶́˶˵˹
/* производитель ресурсов проверяет, есть ли свободные
* слоты для нового запроса и добавляет запрос */
void *producer(void *arg)
{
request_t *request;
for (;;) {
_sem_wait(request_slots);
request = get_request();
add(request);
sem_post(request_length);
}
}
107. ˠ́˿˹˸˳˿˵˹̃˶˼̍̀˿̃́˶˲˹̃˶˼̍̂˿˴́˱˾˹̈˶˾˹˶˽˵˼˹˾̌˿̈˶́˶˵˹
/* потребитель проверяет, есть ли запросы,
* затем увеличивает семафор свободных слотов
* и обрабатывает запрос */
void *consumer(void *arg)
{
request_t *request;
for (;;) {
_sem_wait(requests_lenght);
request = remove();
process_request(request);
sem_post(request_slots);
}
}
111. /* ожидать наступления события cond */
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
/* ожидать наступления события не дольше timeout */
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
/* возобновить работу одного потока,
ожидающего наступления события cond */
int pthread_cond_signal(pthread_cond_t *cond);
/* возобновить работу всех потоков,
* ожидающих наступления события cond */
int pthread_cond_broadcast(pthread_cond_t *cond);
142. ˠ́˿˹˸˳˿˵˹̃˶˼̍̀˿̃́˶˲˹̃˶˼̍̂˿˴́˱˾˹̈˶˾˹˶˽˵˼˹˾̌˿̈˶́˶˵˹
/* производитель (на основе условных переменных) */
void *producer(void *arg)
{
request_t *request;
for (;;) {
pthread_mutex_lock(request_lock);
while (length = 10)
pthread_cond_wait(request_producer,
requests_lock);
add(request);
lenght++;
pthread_mutex_unlock(request_lock);
pthread_cond_signal(request_consumer);
}
}
143. ˠ́˿˹˸˳˿˵˹̃˶˼̍̀˿̃́˶˲˹̃˶˼̍̂˿˴́˱˾˹̈˶˾˹˶˽˵˼˹˾̌˿̈˶́˶˵˹
/* потребитель (на основе условных переменных) */
void *consumer(void *arg)
{
request_t *request;
for (;;) {
pthread_mutex_lock(request_lock);
while (length == 0)
pthread_cond_wait(request_consumer,
requests_lock);
request = remove();
length--;
pthread_mutex_unlock(request_lock);
pthread_cond_signal(request_producer);
process_request(request);
}
}
144. ˝˿˾˹̃˿́̌
● Потокобезопасная инкапсюляция общих данных
● В С - путём объявления всех переменных внутри
функции, которая выполняет доступ
● В С++ - инкапсюляция путем создания объекта
● Мониторы “заставляют” пользователя совершать
действия над общими переменным через код
монитора.
● Мониторы, однако, не позволяют реализовать все
типы блокировок (например, пересекующиеся
блокировки или использование неблокирующих
“trylock” блокировок).
145. ˝˿˾˹̃˿́̌ˡ˶˱˼˹˸˱̇˹̐˾˱ˢ
/* реализация счётчика count - суммы всех i */
void count(int i)
{
static int count = 0;
static pthread_mutex_t countlock =
PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(countlock);
count += i;
i = count;
pthread_mutex_unlock(countlock);
return i;
}
148. ˢ̀˹˾˼˿˻˹
▪ Спинлоки подобны мьютексам, но
▪ Это более простой и быстрый механизм
синхронизации (“testset” или что-то ещё)
▪ Поток, пытаясь запереть спинлок, не блокируется
(если спинлок занят) - вместо этого он циклически
пробует запереть спинлок, пока это у него не получится.
▪ Подходит для мелкозернистого параллелизма (КС
небольшая и блокируется на короткий срок).
▪ Критическая секция является местом частого
возникновения конфликтов.
▪ Для многоядерных систем.
▪ Проблема с приоритетами потоков!
149. ˢ̀˹˾˼˿˻˹
/* инициализация */
int pthread_spin_init(pthread_spinlock_t *lock,
int pshared);
/* уничтожение */
int pthread_spin_destroy(pthread_spinlock_t *lock);
/* запирание мьютекса */
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
/* отпирание мьютекса */
int pthread_spin_unlock(pthread_spinlock_t *lock);
150. ˢ̀˹˾˼˿˻˹
/* инициализация */
int pthread_spin_init(pthread_spinlock_t *lock,
int pshared);
/* уничтожение */
int pthread_spin_destroy(pthread_spinlock_t *lock);
/* запирание мьютекса */
int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
/* отпирание мьютекса */
int pthread_spin_unlock(pthread_spinlock_t *lock);
151. ˢ̀˹˾˼˿˻˹
pthread_spinlock_t spinlock;
rc = pthread_spin_init(spinlock, PTHREAD_PROCESS_PRIVATE);
if (rc != 0)
/* … */
/* … */
pthread_spin_lock(spinlock);
/* “лёгкая” критическая секция,
* которая выполняется очень быстро */
if a[i] k
count++;
pthread_spin_unlock(spinlock);
/* … */
pthread_spin_destory(spinlock);
152. ˒˱́̍˶́̌
▪ Позволяют выполнить синхронизацию для множества
потоков.
▪ Достигшие барьера потоки блокируются до тех пор,
пока все потоки множества не достигнут барьера.
▫ По достижении барьера, поток уменьшает счётчик
барьера и засыпает.
▫ Когда последний поток достигает барьера, он уменьшает
счётчик до 0 и разблокирует все потоки.
153. ˒˱́̍˶́̌
▪ Позволяют выполнить синхронизацию для множества
потоков.
▪ Достигшие барьера потоки блокируются до тех пор,
пока все потоки множества не достигнут барьера.
▫ По достижении барьера, поток уменьшает счётчик
барьера и засыпает.
▫ Когда последний поток достигает барьера, он уменьшает
счётчик до 0 и разблокирует все потоки.
154. ˒˱́̍˶́̌
▪ Позволяют выполнить синхронизацию для множества
потоков.
▪ Достигшие барьера потоки блокируются до тех пор,
пока все потоки множества не достигнут барьера.
▫ По достижении барьера, поток уменьшает счётчик
барьера и засыпает.
▫ Когда последний поток достигает барьера, он уменьшает
счётчик до 0 и разблокирует все потоки.
155. ˒˱́̍˶́̌
▪ Позволяют выполнить синхронизацию для множества
потоков.
▪ Достигшие барьера потоки блокируются до тех пор,
пока все потоки множества не достигнут барьера.
▫ По достижении барьера, поток уменьшает счётчик
барьера и засыпает.
▫ Когда последний поток достигает барьера, он уменьшает
счётчик до 0 и разблокирует все потоки.
156. ˒˱́̍˶́̌
▪ Позволяют выполнить синхронизацию для множества
потоков.
▪ Достигшие барьера потоки блокируются до тех пор,
пока все потоки множества не достигнут барьера.
▫ По достижении барьера, поток уменьшает счётчик
барьера и засыпает.
▫ Когда последний поток достигает барьера, он уменьшает
счётчик до 0 и разблокирует все потоки.
157. ˒˱́̍˶́̌
▪ Позволяют выполнить синхронизацию для множества
потоков.
▪ Достигшие барьера потоки блокируются до тех пор,
пока все потоки множества не достигнут барьера.
▫ По достижении барьера, поток уменьшает счётчик
барьера и засыпает.
▫ Когда последний поток достигает барьера, он уменьшает
счётчик до 0 и разблокирует все потоки.
158. ˒˱́̍˶́̌
/* инициализация и уничтожение */
int pthread_barrier_init(pthread_barrier_t *restrict barrier,
const pthread_barrierattr_t *restrict attr,
unsigned count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);
/* синхронизовать потоки в точке вызова функции */
int pthread_barrier_wait(pthread_barrier_t *barrier);
/* инициализация уничтожение атрибутов */
int pthread_barrierattr_init(pthread_barrierattr_t *attr);
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);
/* задание атрибутов (PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE)*/
int pthread_barrierattr_getpshared(const pthread_barrierattr_t
*restrict attr,
int *restrict pshared);
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr,
int pshared);
160. ˒˱́̍˶́̌ˠ́˹˽˶́
1. Проинициализировать массив а.
2. Параллельно домножить все элемента массива на k.
3. Вывести полученный массив на экран.
4. Параллельно вычислить квадратный корень над
всеми элементами массива.
5. Вывести полученный массив на экран.
6. Параллельно вычислить остаток от деления на 2 всех
элементов массива.
7. Вывести полученный массив на экран.
Сколько необходимо барьеров?
(если без иных средств синхронизации)