Cuda cudaMemcpy и cudaMalloc

#c #c #cuda

#c #c #cuda

Вопрос:

я всегда читал, что выделение и передача данных из cpu в gpu происходит медленно. это потому, что cudaMalloc работает медленно? это потому, что cudaMemcpy работает медленно? или это потому, что оба они медленные?

Ответ №1:

В основном это связано с двумя вещами, первая из которых определяет скорость шины PCIExpress между картой и процессором. Другой связан с тем, как работают эти функции. Теперь, я думаю, что новый CUDA 4 имеет лучшую поддержку выделения памяти (стандартную или закрепленную) и способ прозрачного доступа к памяти по шине.

Теперь давайте посмотрим правде в глаза: в какой-то момент вам понадобится получить данные из точки A в точку B, чтобы что-то вычислить. Лучший способ справиться с этим — либо выполнить действительно большие вычисления, либо использовать потоки CUDA для перекрытия передачи и вычислений на графическом процессоре.

Ответ №2:

В большинстве приложений вы должны выполнять cudaMalloc один раз в начале, а затем больше не вызывать его. Таким образом, узким местом на самом деле является cudaMemcpy.

Это связано с физическими ограничениями. Для стандартного соединения PCI-E 2.0 x16 теоретически вы получите 8 ГБ / с, но на практике обычно 5-6 ГБ / с. Сравните это даже с Fermi среднего уровня, таким как GTX460, пропускная способность которого превышает 80 Гбит / с. Фактически вы на порядок сокращаете пропускную способность памяти, соответственно увеличивая время передачи данных.

Предполагается, что GPGPU являются суперкомпьютерами, и я верю, что Сеймур Крэй (специалист по суперкомпьютерам) сказал: «суперкомпьютер превращает проблемы, связанные с вычислениями, в проблемы, связанные с вводом-выводом». Таким образом, оптимизация передачи данных — это все.

По моему личному опыту, итеративные алгоритмы — это те, которые на сегодняшний день демонстрируют наилучшие улучшения при переносе на GPGPU (на 2-3 порядка величины) из-за того, что вы можете сократить время передачи, сохранив все на месте на GPU.

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

1. в моем случае все наоборот …. я делаю один cudaMemcpy и много cudaMalloc….

2. Не могли бы вы подробнее рассказать о своем приложении? Вы просто храните много преобразованных копий?

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