2014-12-12 2 views
2

Я разрабатываю симуляцию на основе GPU с использованием OpenGL и GLSL-Shaders, и я обнаружил, что производительность увеличивается, когда я добавляю дополнительные (ненужные) GL-команды.Runtime моделирования на основе GPU необъяснимо?

Моделирование выполняется полностью на графическом процессоре без каких-либо переводов и в основном состоит из цикла, выполняющего алгоритмически идентичные по времени 2500 шагов. Я тщательно реализовал кеширование однотипных местоположений GLSL и удалил любые запросы GL-состояния (glGet * и т. Д.), Чтобы максимизировать скорость. Чтобы измерить время настенных часов, я поместил glFinish после основного цикла и через некоторое время истек.

СЛУЧАЙ A: Нормальное общее время выполнения всех итераций 490ms.

СЛУЧАЙ B: Теперь, если я добавить один дополнительный glGetUniformLocation(...) команду в конце каждого временного шага, он требует только 475ms в целом, что 3 процента быстрее. (Обратите внимание, что это относится ко мне, так как позже я буду выполнять намного больше времени)

Я просмотрел временную шкалу, зафиксированную Nvidia nsight, и обнаружил, что в случае A все команды opengl выдаются в течение первого 140 мс, а glFinish занимает 348 мс до завершения всего GPU-работы. В случае, если выдача команд opengl распространяется на значительно более длительное время (410 мс), а glFinish занимает всего 64 мс, что дает более быстрые 475 мс.

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

Так что мои вопросы:

  • Почему B быстрее?
  • Почему пакеты команд выпущены более равномерно для очереди оборудования в течение времени в случае A?
  • Как повысить скорость без добавления дополнительных команд?

Я использую Visual C++, VS2008 на Win7 x64.

+0

Сигнальный шум? 3 процента по всему кадру немного малы. –

+0

Это будет самый воспроизводимый шум когда-либо;) Процесс имеет высокий приоритет, одно ядро, и результаты могут быть воспроизведены с помощью 50 000 шагов времени. Также стандартное отклонение в обоих случаях составляет менее 2 мс. – Thomas

+0

glGetUniformLocation закроет трубопровод. Именно по этой причине вызов glFinish выполняется быстрее в B. В glFinish ожидает, пока все команды opengl, ранее выпущенные, закончены, а в B glGetUniformLocation выполнит ожидание. – BDL

ответ

0

ИМХО этот вопрос не может быть однозначно определен. Для того, что стоит экспериментально определить, glFinish (и ... SwapBuffers, если на то пошло) имеют странное поведение времени выполнения. В настоящее время я разрабатываю свою собственную библиотеку рендеринга VR, и до этого я потратил некоторое значительное время на профилирование графиков команд OpenGL и их взаимодействие с графической системой. И я выяснил, что единственное, что согласуется с тем, что glFinish + ... SwapBuffers имеют очень непоследовательное временное поведение.

Может случиться так, что этот вызов glGetUniformLocation вытащит драйвер OpenGL в состояние «занято». Если вы сразу вызове glFinish, он может использовать другой метод ожидания (например, он может вращаться в цикле while, ожидающем флаг) для графического процессора, чем если вы просто вызываете glFinish (например, можете ждать сигнала или условия переменная и, следовательно, подчиняется режиму планирования ядер).

+0

Итак, если я правильно понял, вы говорите, что во время длинного glFinish в случае A обработка оставшихся вызовов может не быть принудительно, что быстрая или какая-то другая планировка windows-wddm или тому подобное может вмешаться и вызвать задержки? Это звучит возможно - любая идея, если sth можно сделать, кроме угадывания вставки бесполезных команд, чтобы получить случай B или даже лучше? Другой связанный с этим вопрос заключается в том, можно ли каким-либо образом скорректировать размер или интервал обновления командного файла wddm или драйвера? – Thomas

+0

@Thomas: О, я думаю, что команды выполняются как можно быстрее, просто отлично. Просто сам вызов glFinish имеет большую вариацию в времени, которое требуется, чтобы вернуться к вызывающему. Нет, я еще не знаю, как улучшить его. Но я изучаю это. – datenwolf

+0

Как вы можете проверить время glFinish? Если в конвейере есть другие команды, время glFinish зависит от времени их завершения, в противном случае время, затраченное на glFinish, будет зависеть от времени, в течение которого драйвер и wddm должны переключиться в контекст приложения за какое-то время, проверьте конвейер и понимаем, что больше нечего кончать. В обоих случаях вариация естественно довольно высокая, не так ли? Я не могу себе представить, что glFinish сам заберет больше 15 мс в случае А каждый раз ...? – Thomas