Два последовательных ядра или синхронизация по группам из всей сетки? - PullRequest
0 голосов
/ 08 января 2019

Предположим, у меня есть две задачи для запуска на графическом процессоре, вторая из которых основывается на практически всех работах первой. Традиционно мне, по сути, приходилось писать эти задачи как два отдельных ядра и планировать запуск второго в какой-то момент после первого. Но - с помощью CUDA 9 теперь я могу синхронизировать всю сетку, завершив работу над первым заданием - с помощью функции кооперативных групп , а затем приступить к работе сетки со вторым заданием.

Мои вопросы:

  • Можем ли мы предоставить практическое правило относительно того, когда лучше, с точки зрения производительности, писать два ядра и когда использовать синхронизацию по всей сетке?
  • Если так, что бы это было?
  • Если нет - почему трудно определить, какой вариант предпочтительнее и в каких случаях?

1 Ответ

0 голосов
/ 08 января 2019

Делая это CW ответом, чтобы другие не стеснялись добавлять свои мнения и редактировать.

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

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

Чтобы компенсировать это возможное снижение производительности программиста, возможны следующие преимущества:

  1. В ситуации, когда накладные расходы на запуск являются значительной частью общего времени выполнения, совместная синхронизация по всей сетке может дать существенную выгоду. В дополнение к объединению двух отдельных ядер, алгоритмы, которые могут вызывать ядра в цикле, например, итерация / релаксация jacobi, или другие алгоритмы моделирования временного шага, могут заметно выиграть, поскольку цикл запуска может эффективно «перемещаться в GPU», замена цикла запуска ядра одним вызовом ядра.

  2. В ситуации, когда имеется значительное количество "состояния" на кристалле (например, содержимое регистра, содержимое совместно используемой памяти), которое необходимо загрузить до синхронизации всей сетки и будет использовано после синхронизация по всей сетке, тогда кооперативные группы могут быть значительным выигрышем, экономя время в ядре, которое следовало бы после этой синхронизации по всей сетке, которое использовалось бы для повторной загрузки состояния. Это, кажется, было мотивацией здесь (см. Раздел 4.3), например. Я не предполагаю, что они использовали кооперативные группы (они не были). Я полагаю, что они были заинтересованы в поиске синхронизации всей сетки, используя временные методы, доступные в то время, чтобы исключить как стоимость перезагрузки состояния, так и, возможно, затраты на запуск ядра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...