Вызовы WGL снижают производительность выделения памяти в системах Nvidia
У нас возникают серьезные проблемы с производительностью в нашем приложении C++, которое использует WGL для создания окон (и OpenGL для рендеринга) в некоторых системах с видеокартами Nvidia. Как только окно создано, или, точнее, как только вызывается ChoosePixelFormat или SetPixelFormat, выделение памяти происходит значительно медленнее в течение всего времени жизни процесса. Это происходит на множестве различных систем, к которым у нас есть доступ, но это наиболее заметно для Quadro M6000 12 ГБ (версия драйвера 385.69) и Titan Xp (версия драйвера 387.92) в Windows 8.1 Pro 64 bit и Windows 10 Enterprise 64 bit, В меньшей степени этот эффект также измерим для карт GeForce и в 64-разрядной версии Windows 7 Professional.
Я сделал небольшое тестовое приложение, демонстрирующее проблему. Мы выполняем дорогостоящее задание, которое включает в себя много выделения памяти, затем создаем окно с WGL, вызываем ChoosePixelFormat, удаляем окно и затем снова выполняем такое же дорогое выделение памяти. Распределение памяти синхронизировано и выводится на консоль. На всех системах, на которых мы тестировали это (шесть разных карт, три операционные системы), после вызова ChoosePixelFormat распределение памяти было заметно (между 5 % и 20 %) медленнее. Однако, когда мы добавили Quadro или Titan Xp в систему, распределение памяти после ChoosePixelFormat заняло более 300 % от предыдущего времени.
Результаты некоторых тестов (мы поменяли карты между системами, чтобы охватить почти каждую комбинацию, но мы не сохранили все тесты, но это значимое подмножество):
Titan Xp, Windows 8.1 Pro 64 bit
Before Window Creation
Testing memory allocation performance 1 / 3: 5.20743 seconds
Testing memory allocation performance 2 / 3: 5.60933 seconds
Testing memory allocation performance 3 / 3: 5.4247 seconds
After Window Creation
Testing memory allocation performance 1 / 3: 18.0398 seconds
Testing memory allocation performance 2 / 3: 17.9902 seconds
Testing memory allocation performance 3 / 3: 17.9052 seconds
GTX 770, Windows 7 Professional 64 bit
Before Window Creation
Testing memory allocation performance 1 / 3: 4.66427 seconds
Testing memory allocation performance 2 / 3: 4.65927 seconds
Testing memory allocation performance 3 / 3: 4.62726 seconds
After Window Creation
Testing memory allocation performance 1 / 3: 5.69533 seconds
Testing memory allocation performance 2 / 3: 5.71333 seconds
Testing memory allocation performance 3 / 3: 5.72833 seconds
GTX 1080, Windows 8.1 Pro 64 bit
Before Window Creation
Testing memory allocation performance 1 / 3: 5.35666 seconds
Testing memory allocation performance 2 / 3: 5.37008 seconds
Testing memory allocation performance 3 / 3: 5.36607 seconds
After Window Creation
Testing memory allocation performance 1 / 3: 5.7112 seconds
Testing memory allocation performance 2 / 3: 5.69939 seconds
Testing memory allocation performance 3 / 3: 5.71902 seconds
Я вспомнил старый трюк, который я использовал на своем ноутбуке Optimus, чтобы автоматически создаваемые приложения автоматически использовали дискретный графический процессор Nvidia: переименуйте исполняемый файл в wow.exe. Я попробовал это, и, конечно, это работает. Проблемы с производительностью исчезли как в нашем реальном приложении, так и в тестовом приложении. На Titan Xp распределение памяти после вызова ChoosePixelFormat чудесным образом происходит даже быстрее, чем до его вызова. Я почти уверен, что это происходит из-за специального ветвления в драйвере видео, сделанного для World of Warcraft, который обходит некоторые "особенности", которые усложняют нашу жизнь. Так что теперь мы можем назвать это днем и отправить наше программное обеспечение с именем wow.exe, но в какой-то момент клиенты могут спросить, что означает это имя, и нам придется придумать умную аббревиатуру или ребрендинг. Это не постоянное решение, а довольно странный результат отладки. ("Что производители видеокарт не хотят, чтобы вы знали: увеличьте производительность ваших 3D-приложений с помощью этого простого трюка!")
При отладке связанного тестового приложения вы можете видеть, что при создании окна один или несколько потоков создаются видеодрайвером, который продолжает работать после разрушения окна. Мы подозреваем, что они так или иначе вовлечены во все это. Однако у нас нет ни времени, ни бюджета для дальнейшего расследования.
Какие у нас есть варианты, кроме названия нашего программного обеспечения wow.exe, перехода на GTX 1080s или ожидания ответа Nvidia на наши запросы в службу поддержки, чего они не делали раз в четыре года? Кто-нибудь когда-нибудь сталкивался и успешно преодолевал эту проблему? Есть ли способ обойти ChoosePixelFormat и SetPixelFormat при создании окна и контекста OpenGL (4.5 ядра) с WGL в Windows 7/8.1/10? (Мы также попытались настроить окно с GLFW, но я почти уверен, что это вызывает WGL под капотом - результаты были одинаковыми.) Кроме того, мы были бы очень заинтересованы в любом комментарии от кого-то с картой Maxwell или Pascal Quadro или Titan Xp, который не испытывает этих проблем. Возможно, небольшое изменение в нашей настройке может помочь.
PS: Хотя эта проблема звучит немного странно, мы не первые, кто столкнулся с ней. Это было описано ранее, но, видимо, Nvidia не нашла времени, чтобы ответить или заняться проблемой.