Разделяемая память и синхронизация

Опубликовано мая 4, 2018 в Технология CUDA

До сих пор единственным побудительным мотивом расщепления блоков на нити было стремление обойти аппаратные ограничения на количество одновременно работающих блоков. Это довольно слабая мотивация, потому что исполняющая среда CUDA могла бы и сама справиться с этой задачей. Но есть и другие причины.

Язык CUDA С предоставляет в распоряжение программы так называемую разделяемую память.

С этой областью памяти связано еще одно расширениеязыка С, близкое к ключевым словам_device_и_global_. Если в объявление любой переменной добавить ключевое слово _shared_, то эта переменная будетразмещена в разделяемой памяти.

Но зачем это нужно?

Разделяемая память и синхронизация
Вам нужен срочный и недорогой ремонт iPhone в Санкт-Петербурге? Наш сервисный центр AppCenter ответит Вам на этот вопросвопрос: где починить iPhone appcenter.spb.ru

Рады, что вы спросили. Компилятор CUDA С обрабатывает переменные в разделяемой памяти иначе, чем обычные переменные. Он создает копию такой переменной в каждом блоке, запускаемом на GPU. Все нити, работающие в одном блоке, разделяют эту переменную, но не могут ни увидеть, ни модифицировать ее копии, видимые в других блоках. Это создаст прекрасный механизм взаимодействия и кооперации нитей, находящихся водном блоке.

Кроме того, буферы разделяемой памяти физически находятся в самом GPU, а не в DRAM (динамическое запоминающее устройство с произвольной выборкой) вне кристалла. Это означает, что время задержки при доступе к разделяемой памяти существенно меньше, чем при доступе к обычным буферам, то есть разделяемая память играет роль внутриблочного программно управляемого кэша.

Перспективы взаимодействия между нитями должны вас вдохновлять. Нас они тоже вдохновляют. Но ничто в жизни не дается бесплатно, и межнитевое взаимодействие — не исключение. Если мы хотим, чтобы нити взаимодействовали, то необходим и механизм синхронизации. Например, если нить А записывает какое-то значение в разделяемую память, а нить В должна что-то с этим значением сделать, то нить В не должна приступать к работе, пока нить А не сделала свое дело.

Без синхронизации возникла бы «гонка» (race condition), и правильность результата оказалась бы зависящей от недетерминированных особенностей работы оборудования. Рассмотрим пример, в котором эти средства используются.