Подтвердить что ты не робот

Как управляется память CUDA?

Когда я запускаю свою программу CUDA, которая выделяет только небольшое количество глобальной памяти (ниже 20 М), я получил ошибку "из памяти". (Из сообщений других людей, я думаю, проблема связана с фрагментацией памяти). Я пытаюсь понять эту проблему и понимаю, что у меня есть пара вопросов, связанных с управлением памятью CUDA.

  • Существует ли концепция виртуальной памяти в CUDA?

  • Если разрешено запускать только одно ядро ​​на CUDA одновременно, после его завершения будет выпущена ли вся память, которую он использовал или выделил? Если нет, когда эта память освободилась?

  • Если на CUDA разрешено запускать несколько ядер, как они могут убедиться, что используемая память не перекрывается?

Может ли кто-нибудь помочь мне ответить на эти вопросы? Благодаря

Изменить 1: операционная система: x86_64 GNU/Linux Версия CUDA: 4.0 Устройство: Geforce 200, это один из GPUS, подключенных к аппарату, и я не думаю, что это устройство отображения.

Изменить 2: Ниже приводится то, что я получил после некоторых исследований. Не стесняйтесь меня исправлять.

  • CUDA создаст один контекст для каждого потока хоста. Этот контекст сохранит информацию, такую ​​как часть памяти (предварительно выделенная память или динамически распределенная память), зарезервирована для этого приложения, чтобы другое приложение не могло ее записать. Когда это приложение завершается (не ядро), эта часть памяти будет освобождена.

  • Память CUDA поддерживается списком ссылок. Когда приложение должно выделять память, он перейдет через этот список ссылок, чтобы узнать, есть ли доступный объем памяти для выделения. Если ему не удастся найти такой кусок, ошибка "вне памяти" будет сообщаться пользователям, даже если общий объем доступной памяти больше запрашиваемой памяти. И это проблема, связанная с фрагментацией памяти.

  • cuMemGetInfo расскажет вам, сколько памяти свободна, но не обязательно, сколько памяти вы можете выделить в максимальном распределении из-за фрагментации памяти.

  • На платформе Vista (WDDM) возможна виртуализация памяти GPU. То есть, несколько приложений могут выделять почти всю память GPU, а WDDM будет управлять свопированием данных обратно в основную память.

Новые вопросы: 1. Если память, зарезервированная в контексте, будет полностью освобождена после завершения приложения, фрагментация памяти не должна существовать. Должны быть какие-то данные, оставшиеся в памяти. 2. Есть ли способ реструктурировать память GPU?

4b9b3361

Ответ 1

Память устройства, доступная вашему коду во время выполнения, в основном рассчитывается как

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)

если вы получаете сообщение из памяти, то, вероятно, один или несколько из первых трех элементов потребляют большую часть памяти GPU, прежде чем ваш код пользователя попытается получить память в графическом процессоре. Если, как вы указали, вы не работаете на графическом дисплее, то статические распределения контекста являются наиболее вероятным источником вашей проблемы. CUDA работает, предварительно распределяя всю память, которую требует контекст во время установления контекста на устройстве. Есть много вещей, которые выделяются для поддержки контекста, но единственным крупнейшим потребителем в контексте является локальная память. Время выполнения должно резервировать максимальное количество локальной памяти, которое будет потреблять любое ядро ​​в контексте для максимального количества потоков, которые каждый мультипроцессор может запускать одновременно, для каждого мультипроцесса на устройстве. Это может работать сотнями мегабайт памяти, если тяжелое ядро ​​локальной памяти загружается на устройство с большим количеством многопроцессоров.

Лучший способ увидеть, что может быть, это написать хост-программу без кода устройства, который устанавливает контекст и вызывает cudaMemGetInfo. Это покажет вам, сколько памяти имеет устройство с минимальными накладными расходами на нем. Затем запустите ваш проблемный код, добавив тот же вызов cudaMemGetInfo перед первым вызовом cudaMalloc, который затем даст вам объем памяти, который использует ваш контекст. Это может позволить вам получить информацию о том, куда идет память. Очень маловероятно, что фрагментация является проблемой, если вы получаете отказ при первом вызове cudaMalloc.

Ответ 2

  • Отладочная память GPU разделяется в глобальной, локальной и постоянной памяти. Эти три типа памяти являются концепцией виртуальной памяти. Глобальная память бесплатна для всех потоков, локальная - только для одного потока (в основном используется для разлива регистров), а постоянная память кэшируется глобальной памятью (записывается только из кода хоста). Взгляните на 5.3.2 из руководства по программированию CUDA C.

  • ИЗМЕНИТЬ: удалено

  • Память, выделяемая через cudaMalloc, никогда не перекрывается. Для памяти, выделяемой ядром во время выполнения, должно быть достаточно памяти. Если вы потеряли память и попытаетесь запустить ядро ​​(только предположение от меня), вы должны получить сообщение об ошибке "неизвестной ошибки". Драйвер, который не смог запустить и/или выполнить ядро.