В общем, вы хотите, чтобы размер блоков/сетки соответствовал вашим данным и одновременно увеличивал количество занятых, то есть сколько потоков было активным за один раз. Основными факторами, влияющими на занятость, являются использование общей памяти, использование регистров и размер блока потока.
Графический процессор с поддержкой CUDA имеет свои возможности обработки, разделенные на SMs (потоковые мультипроцессоры), а количество SM зависит от реальной карты, но здесь мы сосредоточимся на одном SM для простоты (все они ведут себя одинаково). Каждый SM имеет конечное число 32-битных регистров, разделяемую память, максимальное количество активных блоков и максимальное количество активных потоков. Эти числа зависят от CC (вычислительная способность) вашего GPU и могут быть найдены в середине статьи Википедии http://en.wikipedia.org/wiki/CUDA.
Прежде всего, размер блока потока всегда должен быть кратным 32, потому что ядра выдают инструкции в деформациях (32 потока).Например, если у вас размер блока 50 потоков, GPU по-прежнему выдаст команды для 64 потоков, и вы просто будете их тратить.
Во-вторых, прежде чем беспокоиться об общей памяти и регистрах, попробуйте размер блоков на основе максимального количества потоков и блоков, соответствующих вычислительной способности вашей карты. Иногда есть несколько способов сделать это ... например, карта CC 3.0 каждый SM может иметь 16 активных блоков и 2048 активных потоков. Это означает, что если у вас есть 128 потоков на блок, вы можете поместить 16 блоков в свой SM, прежде чем достигнуть предела потока 2048. Если вы используете 256 потоков, вы можете поместиться только в 8, но вы все еще используете все доступные потоки и по-прежнему будете иметь полное заполнение. Однако при использовании 64 потоков на блок будет использоваться только 1024 потока при ударе по 16 блокам, поэтому только 50% заполняемости. Если разделяемая память и использование регистров не являются узким местом, это должно быть вашей главной проблемой (кроме ваших размеров данных).
По теме вашей сетки ... блоки в вашей сетке распределяются по SM для запуска, а затем остальные блоки помещаются в конвейер. Блоки перемещаются в SM для обработки, как только в этом SM достаточно ресурсов, чтобы взять блок. Другими словами, когда блоки завершены в SM, новые перемещаются. Вы можете сделать аргумент о том, что меньшие блоки (128 вместо 256 в предыдущем примере) могут завершиться быстрее, поскольку особенно медленный блок будет обрабатывать меньше ресурсов, но это очень сильно зависит от кода.
Что касается регистров и разделяемой памяти, посмотрите на следующее, так как это может ограничивать ваше размещение. Общая память ограничена для всего SM, поэтому попробуйте использовать ее в количестве, которое позволяет как можно больше блоков по-прежнему поместиться на SM. То же самое касается использования регистра. Опять же, эти числа зависят от вычислительной способности и могут быть найдены в таблице на странице wikipedia. Удачи!
Почему мы не можем рассчитать блоки/потоки, используя возможности устройства? Предположим, у меня есть устройство с возможностями 2.1 (GT 520), поэтому он имеет 48 SM, по 8 блоков и 1024 потока на блок. Я не могу это получить, извините, если мой вопрос глупо. – greg 2013-07-18 12:30:17