Максимум (общая память на блок) / (потоков на блок) в CUDA со 100% загрузкой MP
Я пытаюсь обработать массив больших структур с помощью CUDA 2.0 (NVIDIA 590). Я хотел бы использовать общую память для этого. Я экспериментировал с калькулятором занятости CUDA, пытаясь выделить максимум разделяемой памяти для каждого потока, чтобы каждый поток мог обрабатывать весь элемент массива. Однако максимум (общая память на блок) / (потоков на блок), который я вижу в калькуляторе со 100% загрузкой мультипроцессора, составляет 32 байта, что недостаточно для отдельного элемента (порядка величины). Является ли 32 байта максимально возможным значением для (разделяемой памяти на блок) / (потоков на блок)? Можно ли сказать, какой из alter4native предпочтительнее - выделить часть массива в глобальную память или просто использовать перегруженный мультипроцессор? Или это можно решить только экспериментом? Еще одна альтернатива, которую я вижу, - это обработка массива за несколько проходов, но это выглядит как последнее средство. Это первый раз, когда я пытаюсь сделать что-то действительно сложное с CUDA, поэтому я могу упустить некоторые другие варианты...
1 ответ
При проектировании ядра CUDA нужно учитывать множество аппаратных ограничений. Вот некоторые из ограничений, которые необходимо учитывать:
- максимальное количество потоков, которые вы можете запустить в одном блоке
- максимальное количество блоков, которое вы можете загрузить на потоковый мультипроцессор одновременно
- максимальное количество регистров на потоковый мультипроцессор
- максимальный объем разделяемой памяти на потоковый мультипроцессор
Какой бы из этих ограничений вы не установили первым, он становится ограничением, которое ограничивает вашу занятость (является ли максимальная загруженность тем, на что вы ссылаетесь, под "100% многопроцессорной нагрузкой"?). Как только вы достигаете определенного порога занятости, становится менее важным обращать внимание на занятость. Например, занятость в 33% не означает, что вы сможете достичь только 33% от максимальной теоретической производительности графического процессора. Василий Волков выступил с большой речью на Технологической конференции GPU 2010 года, в которой рекомендует не слишком беспокоиться о загруженности, а вместо этого попытаться минимизировать транзакции памяти, используя некоторые явные приемы кэширования (и другие вещи) в ядре. Вы можете посмотреть выступление здесь: http://www.gputechconf.com/gtcnew/on-demand-GTC.php?sessionTopic=25&searchByKeyword=occupancy&submit=&select=+&sessionEvent=&sessionYear=&sessionFormat=
Единственный реальный способ убедиться, что вы используете дизайн ядра, обеспечивающий наилучшую производительность, - это протестировать все возможности. И вам нужно повторить это тестирование производительности для каждого типа устройства, на котором вы его запускаете, потому что все они имеют разные ограничения в некотором роде. Это, очевидно, может быть утомительным, особенно когда разные шаблоны проектирования приводят к принципиально разным ядрам. Я до некоторой степени обхожу это, используя шаблонизатор для динамического генерирования ядер во время выполнения в соответствии со спецификациями оборудования устройства, но это все еще немного хлопотно.