Qt+OpenGL benchmarking Q

А вот, я извиняюсь, такой вопрос.

Есть QGrahicsScene (унаследованное от нее) в которой я в drawBackround вывожу OpenGL-ем нечто.

В процессе разбирательств с OpenGL я это нечто имплементировал десятком разных способов и хочу теперь померять, какой из них быстрее.

Но как?

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

for(.....){
myview->setZoom(...);
QApplication::processEvents();
}

Но получается вот что:

  • FPS-ов ровно 60 (2000 итераций за 34 секунды), OGLFormat::setSwapInterval(0) не помог.
  • Одно ядро процессора полностью загружено.
  • По профайлеру, загружено оно QWindowsWindow::raise() (~70% по профайлеру), вообще весь прочий код занимает остальные 30% CPU, моего кода вовсе не видно.

Так слона не продать.

Ну то есть понятно, можно в OpenGL-рисовалке рисовать одно и то же 10 (100,1000) раз подряд, но вопрос заключается в том, нет ли более прямого пути, который позволяет Qt-GUI программы побенчмаркать попроще?

Update: если вдруг кому интересно, то проблема решилась глобальным выключением VSync в настройках драйвера (NVidia). FPS-ы сразу сильно выросли, а профайл исполнения стал похож на настоящий.

Comments

Более менее надежный способ померять opengl это рендерить в текстуру и потом ее прочитать, хотя бы пиксель.

Другой способ это выключить vertical sync, рендерить на полной скорости запоминая при это текущее время и вычетать его из предыдущего. Но тест из этого не сделать.

да, я понимаю.

Но в том виде, который я использую (QGraphicsView в QGLWidget), я вижу изрядный оверхед собственно от Qt. Его и хотелось бы померять.

setSwapInterval оверрайдится настройкой в драйвере и по-моему еще где-то. В общем я эту проблему решил методом довольно долгого гуглования и экспериментирования.

что касается статсов - я их честно спиздил почти один в один из нвидиевского сампла Textureчего-то-тамPBO. Который дает возможность на ходу кнопками переключать разные режимы трансфера и смотреть выигрыш/проигрыш.

вообще, ты не обращай внимания что я тут пишу - я просто наяву вижу как у меня альцгеймер рассасывается, так что это не информация, а просто самолечение.

Не, ты пиши.

Потому что я вот сходил к нвидии на сайт, нашел этот пример (с трудом, он в старом SDK, а в текущем - нет) и наслаждаюсь.

Но вот если vsync не выключать, то все способы аплоада дают одинаковый совершенно результат. А если выключить, то разница, да, есть. Но всего-то раза в полтора, если смотреть на FPS-ы (c учетом того, что еще рендер есть - скорее в два). И 1PBO/2PBO - очень близки, а вот TexSubImage - медленнее.

Спасибо!

Забавно, в мое время (лет 7 тому назад, типа, 6800GT, потом 8800) разница была типа раз в 5 что-ли или около того.

Да, еще удивительно, что конверсия форматов не влияет значимо на время.

Вот прям any to any? В "мое время"™ некоторые форматы были ок, а некоторые явно в драйвере конвертировались методом while(length--) { *dst++ = VBConvertFormat( *src++ ); }

Там не совсем any to any, но вот для целых - примерно одинаковый результат, для float - другой, но тоже примерно одинаковый. Катастрофической заметной разницы не видно.

Т.е. там или в карте все конвертируется (у нее запаса перформанса на это хватит) или просто на фоне скорости трансфера эта конверсия не видна.

Вот я в своем коде потестировал.
600 показов 15-мегапиксельной картинки (полный аплоад каждый раз)
1) По часам: одна хрень, 20 секунд, 30fps. Это, заметим, ~2Gb/sec скорость аплоада. Ровно в эту цифру упирался нвидиевский тест, который ты тут посоветовал. Это мало, CUDA-вские прибабахи намеривают ~4Gb/sec, но порядок величины тот самый.

2) По CPU time в main thread:
glTexSubImage2D(...., data-pointer) - ~15-17 сек. по профилю исполнения
glBufferData(....) + SubImage2D(..,NULL) - 4 секунды в main thread, но завелась заметная активность в thread, который VTune назвал DrvCopyContext и в модуле "outside any known module"

Т.е. мораль такая - что узкое место вроде как в data upload

Совсем дурацкий вопрос. FPS-ы не могут ограничиваться частотой монитора?..

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

После глобального отключения vsync, меж тем, профиль программы (из vtune) стал похож на человеческий.
В частности, Window::raise занимает вполне человеческие несколько процентов, FPS-ы выросли раз в 10 (собственно, 1000 фреймов за 1.5 секунды вместо 100 за то же время).

Ну и видно, что qt тоже делом занимается - ищет всякие пересечения item-ов на сцене, что при 600fps занимает время.

В очередной раз спасибо - я бы это место не нашел.

противно то, что настройка эта глобальная, и по-моему у всех по дефолту on. вроде бы можно принести с собой при инсталляции "профиль приложения" и воткнуть в драйвер, но это надо отдельно делать для всех вендоров, что само по себе какой-то унизительный геморрой.

Вот это волшебное слово - vsync - я успел забыть.

Ну да, 60FPS - это понятно что чисто драйверное ограничение.
Но оно регулируется, по идее, setSwapInterval(0) должен бы это отключить, однако нет.

Набрел тут на билдер qt (разных конфигураций под виндовз)
http://vertexwahn.de/index.html
BlueGo. Собрал 4.8 под vs2012 из исходничков. Креатором подхватился, работает.

И набрел на OpenGL таймер api описанный в OpenGL Insights (есть в электронном виде для ознакомления).
http://www.opengl.org/sdk/docs/man/xhtml/glBeginQuery.xml (линка на доку, не на книжку)

Да я как-то руками собираю, там же проблем никаких особых нет.
configure && nmake

Т.е. у меня все что я пользую - самосборное, а стандартные наборы флагов configure - запомнены в батниках.

и под 2012? там вроде надо hashset как то патчить.

Мой секрет в -no-webkit ибо он мне не нужен :)

Но да, 4.8 вроде надо патчить.

В названии топика и в тэгах s/OpenCL/OpenGL/g

Заметили только те, кому слово OpenCL не пустой звук :)

Ну так я из-за "OpenCL" в названии топик открыл :)
Ведь по-идеи в QT небольшая прослойка/абстракция над OpenCL, запуски ядер обычно достаточно продолжительные (допустим от 0.001с) - трудно представить как именно можно накосячить в прослойке чтобы заметно тормозило.
Либо другой вариант - очень короткие запуски ядер, но тогда интересно какая именно задача..

C OpenCL еще и понятно как мерять. Просто, банально, таймером.

А вот с OpenGL - когда у меня часть OGL-кода - моя, а остальная - Qt-шная и исполняется по event-ам - непонятно.