В CUDA, почему cudaMemcpy2D и cudaMallocPitch занимают много времени

#performance #cuda #gpu #nvidia #memory-bandwidth

#Производительность #cuda #графический процессор #nvidia #пропускная способность памяти

Вопрос:

Как упоминалось в названии, я обнаружил, что функция cudaMallocPitch() занимает много времени и cudaMemcpy2D() занимает довольно много времени.

Вот код, который я использую:

 cudaMallocPitch((void **)(amp;SrcDst), amp;DeviceStride, Size.width * sizeof(float), Size.height);

cudaMemcpy2D(SrcDst, DeviceStride * sizeof(float), 
        ImgF1, StrideF * sizeof(float), 
        Size.width * sizeof(float), Size.height,
        cudaMemcpyHostToDevice);
  

В реализации Size.width Size.height оба и равны 4800. Время, затрачиваемое на cudaMallocPitch() это, составляет около 150-160 мс (несколько тестов на случай аварий) и cudaMemcpy2D() занимает около 50 мс.

Кажется невозможным, что пропускная способность памяти между CPU и GPU настолько ограничена, но я не вижу никаких ошибок в коде, так в чем причина?

Кстати, аппаратное обеспечение, которое я использую, — это процессор Intel I7-4770K и Nvidia Geforce GTX 780 (довольно хорошее оборудование без ошибок).

Комментарии:

1.Вы пробовали тест пропускной способности для вашей архитектуры для получения ссылки? 4800x4800 float Массив, который требуется 50ms для передачи, означает пропускную способность около 2GB/s . Я не уверен, нужно ли вам также учитывать выделенный шаг в размере матрицы, и в этом случае скорость увеличивается. С закрепленной памятью мой ноутбук, оснащенный картой GT540M, касается 6GB/s .

Ответ №1:

Здесь есть много факторов, которые могут влиять на производительность.

Что касается cudaMallocPitch , если это будет первый вызов cuda в вашей программе, это повлечет за собой дополнительные накладные расходы.

Что касается cudaMemcpy2D , это достигается под капотом с помощью последовательности отдельных операций memcpy, по одной на строку вашей 2D-области (т. Е. 4800 отдельных операций DMA). Это обязательно повлечет за собой дополнительные накладные расходы по сравнению с обычной cudaMemcpy операцией (которая передает всю область данных за одну передачу DMA). Кроме того, пиковые скорости передачи достигаются только тогда, когда закреплен буфер памяти на стороне хоста. Наконец, вы ничего не указываете о своей платформе. Если вы используете Windows, то WDDM будет препятствовать полной производительности передачи для этой операции, и мы не знаем, на каком канале PCIE вы находитесь.

4800*4800*4/0 .050 = 1,84 ГБ / с, что составляет значительную долю от ~ 3 ГБ / с, которые примерно доступны для передачи без закрепления через PCIE 2.0. Сокращение с 3 ГБ до 1,84 ГБ легко объяснимо другими факторами, которые я перечислил выше.

Если вам нужна полная производительность передачи, используйте закрепленную память и не используйте передачу с шагом / 2D.

Комментарии:

1. Этот вопрос касается в первую очередь характеристик передачи хоста <-> устройства. То, будет ли выделенное распределение использоваться для текстурирования, не влияет на характеристики передачи между хостом <->device для этого выделенного распределения.

2. Текстурирование в различных обстоятельствах может выполняться с 1. Линейное выделение памяти 2. Распределенное распределение памяти 3. A cudaArray . Я предполагаю, что ваш вопрос относится к cudaArray . Этого вопроса нет.

3. Если вы спрашиваете cudaArray , я не знаю подробной документации, в которой обсуждаются какие-либо вопросы, о которых вы можете спросить (характеристики передачи хоста-> устройства, базовые шаблоны хранения и т. Д.). Конечно, вы можете задать любой вопрос, который пожелаете.