Skip to content

Commit

Permalink
PGO: Make Python PGO work for standalone mode
Browse files Browse the repository at this point in the history
* Also rename --pgo to make it clear it's about C compiler only
  • Loading branch information
kayhayen committed Jul 11, 2024
1 parent 8d8c560 commit 3c0dd09
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 24 deletions.
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1808,13 +1808,13 @@ run is most meaningful, and eliminates usage spikes.
echo "Uncompiled Python2"
for i in {1..100}; do BENCH=1 python2 tests/benchmarks/pystone.py ; done | sort -rn | head -n 1
python2 -m nuitka --lto=yes --pgo tests/benchmarks/pystone.py
python2 -m nuitka --lto=yes --pgo-c tests/benchmarks/pystone.py
echo "Compiled Python2"
for i in {1..100}; do BENCH=1 ./pystone.bin ; done | sort -n | head -rn 1
echo "Uncompiled Python3"
for i in {1..100}; do BENCH=1 python3 tests/benchmarks/pystone3.py ; done | sort -rn | head -n 1
python3 -m nuitka --lto=yes --pgo tests/benchmarks/pystone3.py
python3 -m nuitka --lto=yes --pgo-c tests/benchmarks/pystone3.py
echo "Compiled Python3"
for i in {1..100}; do BENCH=1 ./pystone3.bin ; done | sort -rn | head -n 1
Expand Down
2 changes: 1 addition & 1 deletion doc/nuitka-run.1
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ clcache (MSVC, clangcl). Same as \fB\-\-disablecache\fR=\fI\,ccache\/\fR.
.IP
PGO compilation choices:
.TP
\fB\-\-pgo\fR
\fB\-\-pgo\-c\fR
Enables C level profile guided optimization (PGO), by
executing a dedicated build first for a profiling run,
and then using the result to feedback into the C
Expand Down
2 changes: 1 addition & 1 deletion doc/nuitka.1
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ clcache (MSVC, clangcl). Same as \fB\-\-disablecache\fR=\fI\,ccache\/\fR.
.IP
PGO compilation choices:
.TP
\fB\-\-pgo\fR
\fB\-\-pgo\-c\fR
Enables C level profile guided optimization (PGO), by
executing a dedicated build first for a profiling run,
and then using the result to feedback into the C
Expand Down
28 changes: 18 additions & 10 deletions nuitka/MainControl.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,12 +544,16 @@ def _runCPgoBinary():

if exit_code_pgo != 0:
pgo_logger.warning(
"Error, PGO compiled program error exited. Make sure it works fully before using '--pgo' option."
"""\
Error, the C PGO compiled program error exited. Make sure it works \
fully before using '--pgo-c' option."""
)

if not pgo_data_collected:
pgo_logger.sysexit(
"Error, no PGO information produced, did the created binary run at all?"
"""\
Error, no C PGO compiled program did not produce expected information, \
did the created binary run at all?"""
)

pgo_logger.info("Successfully collected C level PGO information.", style="blue")
Expand All @@ -567,7 +571,9 @@ def _runPythonPgoBinary():

if not os.path.exists(pgo_filename):
general.sysexit(
"Error, no Python PGO information produced, did the created binary run (exit code %d) as expected?"
"""\
Error, no Python PGO information produced, did the created binary
run (exit code %d) as expected?"""
% exit_code
)

Expand Down Expand Up @@ -629,6 +635,8 @@ def runSconsBackend():
if Options.isOnefileTempDirMode():
options["onefile_temp_mode"] = asBoolStr(True)

# TODO: Some things are going to hate that, we might need to bundle
# for accelerated mode still.
if Options.shallCreateAppBundle():
options["macos_bundle_mode"] = asBoolStr(True)

Expand All @@ -638,6 +646,9 @@ def runSconsBackend():
if Options.getForcedStderrPath():
options["forced_stderr_path"] = Options.getForcedStderrPath()

if Options.isProfile():
options["profile_mode"] = asBoolStr(True)

if Options.shallTreatUninstalledPython():
options["uninstalled_python"] = asBoolStr(True)

Expand All @@ -646,9 +657,6 @@ def runSconsBackend():
len(ModuleRegistry.getUncompiledTechnicalModules())
)

if Options.isProfile():
options["profile_mode"] = asBoolStr(True)

if hasPythonFlagNoWarnings():
options["no_python_warnings"] = asBoolStr(True)

Expand Down Expand Up @@ -715,7 +723,7 @@ def runSconsBackend():
# Allow plugins to build definitions.
env_values.update(Plugins.getBuildDefinitions())

if Options.shallCreatePgoInput():
if Options.shallCreatePythonPgoInput():
options["pgo_mode"] = "python"

result = runScons(
Expand All @@ -734,11 +742,11 @@ def runSconsBackend():
return True, options

# Need to restart compilation from scratch here.
if Options.isPgoMode():
if Options.isCPgoMode():
# For C level PGO, we have a 2 pass system. TODO: Make it more global for onefile
# and standalone mode proper support, which might need data files to be
# there, which currently are not yet there, so it won't run.
if Options.isPgoMode():
if Options.isCPgoMode():
options["pgo_mode"] = "generate"

result = runScons(
Expand Down Expand Up @@ -1004,7 +1012,7 @@ def _main():
)

# Relaunch in case of Python PGO input to be produced.
if Options.shallCreatePgoInput():
if Options.shallCreatePythonPgoInput():
# Will not return.
pgo_filename = OutputDirectories.getPgoRunInputFilename()
general.info(
Expand Down
2 changes: 1 addition & 1 deletion nuitka/OptionParsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,7 @@
pgo_group = parser.add_option_group("PGO compilation choices")

pgo_group.add_option(
"--pgo",
"--pgo-c",
action="store_true",
dest="is_c_pgo",
default=False,
Expand Down
47 changes: 38 additions & 9 deletions nuitka/Options.py
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,8 @@ def commentArgs():
)

if (
not standalone_mode
not shallCreatePythonPgoInput()
and not standalone_mode
and options.follow_all is None
and not options.follow_modules
and not options.follow_stdlib
Expand Down Expand Up @@ -1117,23 +1118,27 @@ def commentArgs():
options.static_libpython = "no"

if (
not isPgoMode()
not isCPgoMode()
and not isPythonPgoMode()
and (getPgoArgs() or getPgoExecutable())
):
Tracing.optimization_logger.warning(
"Providing PGO arguments without enabling PGO mode has no effect."
)

if isPgoMode():
if isCPgoMode():
if isStandaloneMode():
Tracing.optimization_logger.warning(
"Using PGO with standalone/onefile mode is not currently working. Expect errors."
"""\
Using C level PGO with standalone/onefile mode is not \
currently working. Expect errors."""
)

if shallMakeModule():
Tracing.optimization_logger.warning(
"Using PGO with module mode is not currently working. Expect errors."
"""\
Using C level PGO with module mode is not currently \
working. Expect errors."""
)

if (
Expand Down Expand Up @@ -1337,6 +1342,9 @@ def shallFollowNoImports():

def shallFollowAllImports():
""":returns: bool derived from ``--follow-imports``"""
if shallCreatePythonPgoInput() and options.is_standalone:
return True

return options.is_standalone or options.follow_all is True


Expand Down Expand Up @@ -1699,7 +1707,7 @@ def getJobLimit():


def getLtoMode():
""":returns: bool derived from ``--lto`` or ``--pgo``"""
""":returns: bool derived from ``--lto``"""
return options.lto


Expand Down Expand Up @@ -1862,11 +1870,17 @@ def shallExplainImports():

def isStandaloneMode():
""":returns: bool derived from ``--standalone``"""
if shallCreatePythonPgoInput():
return False

return options.is_standalone or options.list_package_dlls


def isOnefileMode():
""":returns: bool derived from ``--onefile``"""
if shallCreatePythonPgoInput():
return False

return options.is_onefile


Expand All @@ -1882,6 +1896,9 @@ def isOnefileTempDirMode():
Using cached onefile execution when the spec doesn't contain
volatile things.
"""
if shallCreatePythonPgoInput():
return False

spec = getOnefileTempDirSpec()

for candidate in (
Expand All @@ -1896,8 +1913,11 @@ def isOnefileTempDirMode():
return False


def isPgoMode():
""":returns: bool derived from ``--pgo``"""
def isCPgoMode():
""":returns: bool derived from ``--pgo-c``"""
if shallCreatePythonPgoInput():
return False

return options.is_c_pgo


Expand All @@ -1911,7 +1931,7 @@ def getPythonPgoInput():
return options.python_pgo_input


def shallCreatePgoInput():
def shallCreatePythonPgoInput():
return isPythonPgoMode() and getPythonPgoInput() is None


Expand Down Expand Up @@ -2142,6 +2162,9 @@ def getMacOSTargetArch():

def shallCreateAppBundle():
"""*bool* shall create an application bundle, derived from ``--macos-create-app-bundle`` value"""
if shallCreatePythonPgoInput():
return False

return options.macos_create_bundle and isMacOS()


Expand Down Expand Up @@ -2412,11 +2435,17 @@ def shallUseProgressBar():

def getForcedStdoutPath():
"""*str* force program stdout output into that filename"""
if shallCreatePythonPgoInput():
return False

return options.force_stdout_spec


def getForcedStderrPath():
"""*str* force program stderr output into that filename"""
if shallCreatePythonPgoInput():
return False

return options.force_stderr_spec


Expand Down

0 comments on commit 3c0dd09

Please sign in to comment.