Я хочу измерить, насколько пиковая пропускная способность памяти архивирует мое ядро.
Допустим, у меня NVIDIA Tesla C1060, максимальная пропускная способность которого составляет 102,4 ГБ / с . В моем ядре у меня есть следующие обращения к глобальной памяти:
...
for(int k=0;k>4000;k++){
float result = (in_data[index]-loc_mem[k]) * (in_data[index]-loc_mem[k]);
....
}
out_data[index]=result;
out_data2[index]=sqrt(result);
...
Я считаю для каждого потока 4000 * 2 + 2 обращений к глобальной памяти. Имея 1.000.000 потоков и все обращения являются плавающими, у меня есть ~ 32 ГБ доступа к глобальной памяти (добавлены входящие и исходящие). Поскольку мое ядро занимает всего 0,1 с, я бы заархивировал ~ 320 ГБ / с, что превышает максимальную пропускную способность, поэтому в моих вычислениях / предположениях есть ошибка. Я предполагаю, что CUDA выполняет некоторое кэширование, поэтому не все обращения к памяти учитываются. Теперь мои вопросы:
- В чем моя ошибка?
- Какие обращения к глобальной памяти кэшируются, а какие нет?
- Правильно ли, что я не считаю доступ к регистрам, локальным, общим и постоянным памяти?
- Можно ли использовать профилировщик CUDA для более простых и точных результатов? Какие счетчики мне нужно использовать? Как бы мне нужно их интерпретировать?
Профилировщик выводит:
method gputime cputime occupancy instruction warp_serial memtransfer
memcpyHtoD 10.944 17 16384
fill 64.32 93 1 14556 0
fill 64.224 83 1 14556 0
memcpyHtoD 10.656 11 16384
fill 64.064 82 1 14556 0
memcpyHtoD 1172.96 1309 4194304
memcpyHtoD 10.688 12 16384
cu_more_regT 93223.906 93241 1 40716656 0
memcpyDtoH 1276.672 1974 4194304
memcpyDtoH 1291.072 2019 4194304
memcpyDtoH 1278.72 2003 4194304
memcpyDtoH 1840 3172 4194304
Новый вопрос:
- Когда 4194304Bytes = 4Bytes *1024* 1024 точек данных = 4MB и gpu_time
~ = 0,1 с, тогда я достигаю пропускную способность 10 * 40MB / с = 400MB / с. Это кажется очень низким. Где ошибка?
p.s. Скажите мне, если вам нужны другие счетчики для вашего ответа.
сестра вопрос: Как рассчитать Gflops ядра