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 оверрайдится настройкой в драйвере и по-моем
setSwapInterval оверрайдится настройкой в драйвере и по-моему еще где-то. В общем я эту проблему решил методом довольно долгого гуглования и экспериментирования.
что касается статсов - я их честно спиздил почти один в один из нвидиевского сампла Textureчего-то-тамPBO. Который дает возможность на ходу кнопками переключать разные режимы трансфера и смотреть выигрыш/проигрыш.
вообще, ты не обращай внимания что я тут пишу - я просто наяву вижу как у меня альцгеймер рассасывается, так что это не информация, а просто самолечение.
Не, ты пиши. Потому что я вот сходил к нвидии на сайт, наше
Не, ты пиши.
Потому что я вот сходил к нвидии на сайт, нашел этот пример (с трудом, он в старом SDK, а в текущем - нет) и наслаждаюсь.
Но вот если vsync не выключать, то все способы аплоада дают одинаковый совершенно результат. А если выключить, то разница, да, есть. Но всего-то раза в полтора, если смотреть на FPS-ы (c учетом того, что еще рендер есть - скорее в два). И 1PBO/2PBO - очень близки, а вот TexSubImage - медленнее.
Спасибо!
Забавно, в мое время (лет 7 тому назад, типа, 6800GT, потом
Забавно, в мое время (лет 7 тому назад, типа, 6800GT, потом 8800) разница была типа раз в 5 что-ли или около того.
Да, еще удивительно, что конверсия форматов не влияет значим
Да, еще удивительно, что конверсия форматов не влияет значимо на время.
Вот прям any to any? В "мое время"™ некоторые форматы
Вот прям any to any? В "мое время"™ некоторые форматы были ок, а некоторые явно в драйвере конвертировались методом while(length--) { *dst++ = VBConvertFormat( *src++ ); }
Там не совсем any to any, но вот для целых - примерно одинак
Там не совсем any to any, но вот для целых - примерно одинаковый результат, для float - другой, но тоже примерно одинаковый.
Катастрофическойзаметной разницы не видно.Т.е. там или в карте все конвертируется (у нее запаса перформанса на это хватит) или просто на фоне скорости трансфера эта конверсия не видна.
Вот я в своем коде потестировал. 600 показов 15-мегапиксельн
Вот я в своем коде потестировал.
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-ы не могут ограничиваться частот
Совсем дурацкий вопрос. FPS-ы не могут ограничиваться частотой монитора?..
могут, конечно. когда включен vsync (который есть и опция в
могут, конечно. когда включен vsync (который есть и опция в драйвере, доступная юзеру и управляется из программы). когда выключен - то программа может шмалять как хочет, но зато при отображении плавного движения может возникнуть эффект tearing, когда на экране часть "прошлого" кадра и немного сдвинутая относительно него остальная часть "нового" кадра. Выглядит как разрыв. В работе с киноматериалом - крайне мерзкая вещь.
После глобального отключения vsync, меж тем, профиль програм
После глобального отключения vsync, меж тем, профиль программы (из vtune) стал похож на человеческий.
В частности, Window::raise занимает вполне человеческие несколько процентов, FPS-ы выросли раз в 10 (собственно, 1000 фреймов за 1.5 секунды вместо 100 за то же время).
Ну и видно, что qt тоже делом занимается - ищет всякие пересечения item-ов на сцене, что при 600fps занимает время.
В очередной раз спасибо - я бы это место не нашел.
противно то, что настройка эта глобальная, и по-моему у всех
противно то, что настройка эта глобальная, и по-моему у всех по дефолту on. вроде бы можно принести с собой при инсталляции "профиль приложения" и воткнуть в драйвер, но это надо отдельно делать для всех вендоров, что само по себе какой-то унизительный геморрой.
Вот это волшебное слово - vsync - я успел забыть.
Вот это волшебное слово - vsync - я успел забыть.
Ну да, 60FPS - это понятно что чисто драйверное ограничение.
Ну да, 60FPS - это понятно что чисто драйверное ограничение.
Но оно регулируется, по идее, setSwapInterval(0) должен бы это отключить, однако нет.
Набрел тут на билдер qt
Набрел тут на билдер 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? там вроде надо
и под 2012? там вроде надо hashset как то патчить.
Мой секрет в -no-webkit ибо
Мой секрет в -no-webkit ибо он мне не нужен :)
Но да, 4.8 вроде надо патчить.
В названии топика и в тэгах
В названии топика и в тэгах s/OpenCL/OpenGL/g
Заметили только те, кому
Заметили только те, кому слово OpenCL не пустой звук :)
Ну так я из-за "OpenCL" в
Ну так я из-за "OpenCL" в названии топик открыл :)
Ведь по-идеи в QT небольшая прослойка/абстракция над OpenCL, запуски ядер обычно достаточно продолжительные (допустим от 0.001с) - трудно представить как именно можно накосячить в прослойке чтобы заметно тормозило.
Либо другой вариант - очень короткие запуски ядер, но тогда интересно какая именно задача..
C OpenCL еще и понятно как
C OpenCL еще и понятно как мерять. Просто, банально, таймером.
А вот с OpenGL - когда у меня часть OGL-кода - моя, а остальная - Qt-шная и исполняется по event-ам - непонятно.