Память устройства, доступная вашему коду во время выполнения, в основном рассчитывается как
Free memory = total memory
- display driver reservations
- CUDA driver reservations
- CUDA context static allocations (local memory, constant memory, device code)
- CUDA context runtime heap (in kernel allocations, recursive call stack, printf buffer, only on Fermi and newer GPUs)
- CUDA context user allocations (global memory, textures)
если вы получаете сообщение о нехватке памяти, вполне вероятно, что один или несколько из первых трех элементов потребляют большую часть памяти графического процессора, прежде чем ваш пользовательский код попытается получить память в графическом процессоре. Если, как вы указали, вы не работаете на графическом процессоре, то статическое распределение контекста является наиболее вероятным источником вашей проблемы. CUDA работает, предварительно выделяя всю память, которая требуется контексту во время установления контекста на устройстве. Есть много вещей, которые выделяются для поддержки контекста, но самый большой потребитель в контексте - это локальная память. Среда выполнения должна зарезервировать максимальный объем локальной памяти, который будет использоваться любым ядром в контексте, для максимального количества потоков, которые каждый мультипроцессор может запустить одновременно, для каждого многопроцессорного устройства. Это может привести к сотням Мб памяти, если на устройстве с большим количеством многопроцессорных систем загружено тяжелое ядро локальной памяти.
Лучший способ увидеть, что может происходить, - это написать хост-программу без кода устройства, который устанавливает контекст и вызывает cudaMemGetInfo
. Это покажет вам, сколько памяти имеет устройство с минимальными затратами контекста на нем. Затем запустите проблемный код, добавив тот же вызов cudaMemGetInfo
перед первым вызовом cudaMalloc
, который даст вам объем памяти, используемый вашим контекстом. Это может позволить вам получить представление о том, куда идет память. Маловероятно, что фрагментация является проблемой, если вы получаете сбой при первом вызове cudaMalloc
.