Функции памяти Cuda выдают неизвестную ошибку при отправке ОЧЕНЬ больших массивов

Моя программа анализирует видеофайл, который представляется в виде трехмерного массива и отправляется из LabView в мою программу. LabView уже сглаживает этот трехмерный массив в одномерный массив, поэтому я только что выделил одномерный массив в CUDA, используя cudaMalloc и cudaMemcpy для копирования данных. Однако я заметил, что если я отправляю более 2XXX изображений размером 120x240 пикселей, я получаю «неизвестную ошибку» от некоторых моих функций памяти cuda (cudamemcpy и cudafree, которые возникают позже в моей программе после вызова нескольких ядер) и в конечном итоге они нарушают мою программу. Однако, если я уменьшу количество изображений, которые я отправляю, у меня не будет проблем. Это наводит меня на мысль, что мой код в порядке, но мои методы распределения памяти плохи.

Для начала поговорим о Pitched memory. Насколько мне известно, все дело в выборе хорошего размера для выделения памяти, чтобы линейные данные не разделялись на два фрагмента. Это особенно характерно для 2D- и 3D-массивов, поскольку вы хотите хранить строки или столбцы вместе в памяти для быстрого доступа.

Могут ли возникнуть такие проблемы, если я не использую память с шагом? Какие ошибки могут возникнуть, если не использовать память с шагом, особенно для таких очень больших массивов? До этого момента я игнорировал возможность использования cudaMallocPitch и cudaMalloc3d, хотя технически у меня есть массивы 2d и 3d, которые я сгладил.

Наконец, как я могу отлаживать проблемы с моим кодом, когда cudaGetLastError сообщает мне только «неизвестная ошибка»? Я могу найти, какая функция виновата, но когда она чем-то похожа на cudaFree, у меня нет возможности отлаживать такие вещи или выяснять, где возникает проблема.

В любом случае спасибо за помощь.


person Shawn Tabrizi    schedule 15.08.2012    source источник


Ответы (1)


Платой за неиспользование основной памяти является скорость. Если два потока пытаются получить доступ к соседним кадрам вашего видео, и кадры размещены в непрерывной памяти (без выравнивания), части одного кадра будут находиться в том же блоке памяти или строке кэша, что и другой кадр, и одному потоку, возможно, придется подождите, пока другой поток не завершит свою операцию с памятью. Наверное, не смертельно, но точно не оптимально. Там также могут быть проблемы с чтением после записи или записью после записи.

Стоимость использования распределенной памяти заключается в том, что это немного увеличит выделение памяти, если размер вашего элемента (кадра или строки сканирования) не является даже кратным предпочтительной границы выравнивания. Начало следующего кадра или строки развертки может быть дополнено несколькими байтами, чтобы оно начиналось на соответствующей границе адреса памяти. Добавление 30 байтов к размеру каждого кадра или строки развертки для получения следующего за соответствующей границей для 2000 кадров добавит около 60 000 байт к общему выделению памяти.

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

Если вашему коду обработки видео необходимо видеть, скажем, 4 последовательных буфера кадров, чтобы выполнить свою работу, вы можете разработать систему управления буфером, которая удаляет самый старый кадр из очереди, когда он больше не нужен, и устанавливает новый кадр в подготовка к следующему вызову ядра. Еще лучше — перезагрузите старую память кадра для нового кадра, чтобы избежать накладных расходов на выделение памяти.

Загружайте только то, что вам нужно, когда (или непосредственно перед) вам это действительно нужно. Вот как 20-долларовые чипы видеоплеера и рекордера обрабатывают многогигабайтные видеопотоки в реальном времени с мизерным объемом реальной оперативной памяти.

person dthorpe    schedule 15.08.2012