#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
, я не знаю подробной документации, в которой обсуждаются какие-либо вопросы, о которых вы можете спросить (характеристики передачи хоста-> устройства, базовые шаблоны хранения и т. Д.). Конечно, вы можете задать любой вопрос, который пожелаете.