Programically setting NvOptimusEnablement for Python-based OpenGL Programs

422 Views Asked by At

Is there a way to programmically set the NvOptimusEnablement flag for a Python-based application using OpenGL (and in particular, those using Qt) from within the Python script?

All the references I've seen so far - e.g. Programmatically selecting integrated graphics in nVidia Optimus, or https://stackoverflow.com/a/39047129/6531515 - are for C/C++, where the flag needs to be set as a global define which is compiled into the executable, but obviously that won't work in this case.

Are the only options to:

  1. Create a custom Python interpreter wrapper with this flag set (e.g. https://github.com/cprogrammer1994/optimuspy), OR
  2. Force users to explicitly tag Python / pyinstaller-created-binary as requiring the Nvidia GPU per machine they use?
1

There are 1 best solutions below

0
On BEST ANSWER

The problem is that those flags have to be known by the system when the process is created. Which makes sense because this is at this point that GPU resources can start being allocated. They only work when exposed from the executable that is run, or a library that is statically linked to it, it won't work with a dynamically linked library.

Therefore, there is no other way than running a Python interpreter that has been compiled with this flag, or configuring which graphics processor Python.exe should use from the Nvidia control panel.

However, when you publish an application using pyinstaller, it is possible to compile the bootloader to have these flags exposed, since it is the entry point of your program. You just have to add this to main.c: (or use my fork of pyinstaller: https://github.com/pvallet/pyinstaller )

__declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;

This post explains how to do it: how to recompile the bootloader of Pyinstaller