Шина памяти вашего GPU не просто ширина 48 байтов (что было бы довольно громоздким, так как это не сила 2). Вместо этого он состоит из 6 каналов памяти по 8 байтов (по 64 бита). Операции с памятью обычно намного шире, чем ширина канала, чтобы использовать режим пакетной памяти. Хорошие размеры транзакций начинаются с 64 байтов, чтобы создать пакет размером 8, который хорошо сочетается с 16 32-битными словами полувращения на вычислительных возможностях 1.x.
128-байтовые транзакции по-прежнему немного быстрее и соответствуют 32-разрядным доступам на основе ширины основы для устройств с возможностью вычисления 2.0 (и выше). Кэш-линии также имеют ширину 128 байтов. Обратите внимание, что все эти обращения должны быть выровнены по кратности ширины транзакции, чтобы сопоставить одну транзакцию с памятью.
Теперь о вашей реальной проблеме, , лучше всего ничего не делать и позволить кешу сортировать его. Это работает так же, как вы явно делаете в общей памяти, просто для того, чтобы это было сделано с помощью аппаратного обеспечения кеша, и для него не нужен код, что должно сделать его немного быстрее. Единственное, о чем нужно беспокоиться, - иметь достаточное количество кеш-памяти, чтобы каждый warp мог иметь необходимые 32 × 32 × 4 байта = 4 Кбайт кэша для ширины слова (например, float) или 8 кбайт для двойного доступа.Это означает, что может быть полезно ограничить количество перекосов, которые одновременно активны, чтобы предотвратить их перекоса строк кэша друг друга.
Для специальных оптимизаций существует также возможность использования векторных типов, таких как float2
или float4
, так как все графические процессоры, поддерживающие CUDA, имеют инструкции по загрузке и хранению, которые отображают 8 или 16 байтов в один поток. Однако при вычислительной способности 2.0 и выше я действительно не вижу никакого преимущества использования их в общем случае транспозиции матрицы, поскольку они еще больше увеличивают размер кэша каждой основы.
Поскольку значение по умолчанию для общей кэш-памяти 16 КБ/48 КБ позволяет использовать четыре перекоса на каждый SM для выполнения транспонирования в любой момент времени (при отсутствии другого доступа к памяти одновременно), вероятно, полезно выбрать настройка общей памяти 48 кБ/16 КБ по умолчанию по умолчанию 16 кБ/48 кБ с использованием cudaDeviceSetCacheConfig()
.
Для полноты я также упомянул, что инструкции shuffle warp, представленные с возможностью вычисления 3.0, позволяют обмениваться данными регистров в пределах основы без прохождения через кэш или через общую память. Подробнее см. В разделе Appendix B.14 руководства по программированию CUDA C.
(Обратите внимание, что версия руководства по программированию существует без этого приложения. Поэтому, если в вашей копии Приложение B.13 есть что-то еще, перезагрузите его через предоставленную ссылку).