Затраты на разлив регистров локальной памяти CUDA

У меня есть ядро, которое использует много регистров и сильно разливает их в локальную память.

    4688 bytes stack frame, 4688 bytes spill stores, 11068 bytes spill loads
ptxas info    : Used 255 registers, 348 bytes cmem[0], 56 bytes cmem[2]

Поскольку утечка кажется довольно высокой, я считаю, что она проходит через кэш L1 или даже L2. Поскольку локальная память является частной для каждого потока, как компилятор объединяет доступ к локальной памяти? Эта память читается в 128-байтовых транзакциях, как глобальная память? С таким количеством утечки я получаю низкое использование пропускной способности памяти (50%). У меня есть подобные ядра без утечки, которые получают до 80% максимальной пропускной способности памяти.

РЕДАКТИРОВАТЬ Я извлек некоторые метрики из с nvprof инструмент. Если я хорошо понимаю методику, упомянутую здесь, то у меня будет значительный объем памяти из-за разлития регистров (4 * 11 попаданий и пропущенных / сумма всех записей в 4 секторах L2 = (4 * (45936 + 4278911)) / (5425005 + 5430832 + 5442361 + 5429185) = 79.6%). Может ли кто-нибудь проверить, прав ли я здесь?

Invocations                                Event Name         Min         Max         Avg
Device "Tesla K40c (0)"
Kernel: mulgg(double const *, double*, int, int, int)
     30        l2_subp0_total_read_sector_queries     5419871     5429821     5425005
     30        l2_subp1_total_read_sector_queries     5426715     5435344     5430832
     30        l2_subp2_total_read_sector_queries     5438339     5446012     5442361
     30        l2_subp3_total_read_sector_queries     5425556     5434009     5429185
     30       l2_subp0_total_write_sector_queries     2748989     2749159     2749093
     30       l2_subp1_total_write_sector_queries     2748424     2748562     2748487
     30       l2_subp2_total_write_sector_queries     2750131     2750287     2750205
     30       l2_subp3_total_write_sector_queries     2749187     2749389     2749278
     30                         l1_local_load_hit       45718       46097       45936
     30                        l1_local_load_miss     4278748     4279071     4278911
     30                        l1_local_store_hit           0           1           0
     30                       l1_local_store_miss     1830664     1830664     1830664

РЕДАКТИРОВАТЬ

Я понял, что это 128-байтовые, а не битовые транзакции, о которых я думал.

1 ответ

Согласно локальной памяти и разлитию регистров, влияние разливов регистров на производительность влечет за собой нечто большее, чем просто объединение, решаемое во время компиляции; более важно: чтение / запись из / в кэш L2 уже довольно дорогая, и вы хотите избежать этого.

В презентации предполагается, что с помощью профилировщика вы можете во время выполнения подсчитать количество запросов L2, связанных с доступом к локальной памяти (LMEM), посмотреть, оказывают ли они существенное влияние на общее количество всех запросов L2, а затем оптимизировать отношение общего доступа к L1. в пользу последнего, посредством одного вызова хоста, например cudaDeviceSetCacheConfig( cudaFuncCachePreferL1);

Надеюсь это поможет.

Другие вопросы по тегам