В устройствах 1.0 у вас было только два варианта:
- Доступ к памяти объединен, и все данные извлекаются за одну транзакцию памяти
- Доступ к памяти не коалесцируется, а данные извлекаются один за другим, следовательно, всегда 16 транзакций памяти (полуванчивание).
В устройствах 1.2 и 1.3, однако, это делается по-другому.
Представьте, что память вашего устройства разделена на куски по 128 байт каждый. Вам нужно столько транзакций с памятью, сколько нужно кусков. Итак:
- если вы получаете идеально слитый доступ, вы получаете 1 транзакцию памяти
- если вы просто сместитесь, вы можете получить 2 транзакции памяти
- если каждый поток обращается к каждому n-му слову, вы можете получить 3, 4 или даже больше транзакций памяти
- в худшем случае вы можете получить 16 транзакций памяти
- но даже если доступ несколько случайный, но локализован, два потока могут попасть в один и тот же кусок, и вам потребуется менее 16 транзакций памяти
Существует так много случаев, поэтому разделение его на две категории: коалесцированные / несвязанные больше не имеет никакого смысла. Вот почему, Cuda Profiler пошел другим путем. Они просто считают количество транзакций в памяти. Чем более случайным является ваш шаблон доступа, тем выше количество транзакций в памяти, даже если у вас одинаковое количество инструкций доступа к памяти.
Выше приведена слегка упрощенная модель. На самом деле транзакция памяти может получить доступ к 128-байтовому, 64-байтовому или 32-байтовому фрагменту - для экономии пропускной способности. Ищите столбцы с загрузкой 128b, загрузкой 64b, загрузкой 32b и сохранением 128b, сохранением 64b, сохранением 32b в профилировщике.