#память #cuda #cpp #linux
Добрый день. Иногда, когда я пытаюсь выделить память, я получаю ошибку "out of memory", хотя функция cudaMemGetInfo возвращает количество свободной памяти, которое больше того, что я пытаюсь выделить. Следовательно, проблема во фрагментации. Возможно ее как-то решить? Есть ли способ разместить элементы массива, под который выделяется память, не один за другим, а разбить массив на кусочки и разместить их в разных областях памяти? Но при этом чтобы работать с ним можно было как с целым массивом.
Ответы
Ответ 1
Приведенная далее идея хорошо работает со стандартной моделью виртуальной памяти х86. Для CUDA она, возможно, будет не вполне применима, но все же... Концептуально это выглядит так: создается свой собственный диспетчер памяти, который в начале работы программы захватывает большой кусок непрерывной памяти и постоянно ее удерживает. Все прочие компоненты (его клиенты) обращаются к нему за требуемой памятью, а он в свою очередь помечает ее как используемую и выдает клиентам. При освобождении же памяти клиентами происходит просто снятие признака занятости, и эта память становится доступна другим компонентам. Это весьма эффективный способ борьбы с фрагментацией памяти. Разумеется, при реализации надо учесть ряд тонкостей, таких как характер выделения памяти (или гранулярность, например, по-страницам), режим освобождения (образование дыр занятой памяти в свободной при непоследовательном ее освобождении) и пр.Ответ 2
Вот именно как с целым массивом - сильно сомневаюсь, что такое можно сделать на CUDA'е. В настольных системах есть такой механизм - мепирование страниц, и то, он является скорее побочным продуктом требований масштабируемости систем, поскольку и ОЗУ у них динамическая и механизм подкачки реализуется. На CUDA'е память скорее регистровая, статическая. Это не требует ее виртуального отображения, поэтому мепирование физических страниц на виртуальные там не требуется. Вот именно мепирование и может такое творить: представлять разнородные физические страницы для пользователя в виде последовательной, плоской памяти. Но даже если в какой-то момент память на CUDA'е станет расширяемой, по типу настольных систем, все равно мепирование происходит постранично. Т.е. при распределении таких массивов будут кратные ограничения на число страниц такого массива, в зависимости от размера его элементов, т.е. все равно небольшая, но фрагментация такой памяти будет присутствовать. Альтернативно задачу можно решить с помощью списка массивов: при выделении набора элементов, если не хватает памяти, делим выборку пополам и пытаемся распределить массивы меньшего размера и т.д., пока не будет выделен весь массив.
Комментариев нет:
Отправить комментарий