Skip to content

Parallelize LTO when compiling with GCC#313

Merged
daid merged 1 commit into
daid:masterfrom
oznogon:parallelize-lto
May 2, 2026
Merged

Parallelize LTO when compiling with GCC#313
daid merged 1 commit into
daid:masterfrom
oznogon:parallelize-lto

Conversation

@oznogon

@oznogon oznogon commented May 2, 2026

Copy link
Copy Markdown
Contributor

When building EE/SP with GCC and LTO enabled, GCC reports handling 95 LTRANS partitions. GCC 15 and 16 default to using only 1 core during linking when passed -flto with no option suffixed, so it handles each partition sequentially while the rest of the system idles.

GCC 10 and onward allow passing a number of threads as an option to the flag (i.e. -flto=4) or auto to use all available. Explicitly pass -flto=auto when compiling with GCC to ensure that it parallelizes linking.

This increases linking performance at a cost of increased memory usage. Build instructions should note that building on extremely resource-constrained systems (4GB RAM or less) might benefit from removing =auto if building with LTO, although from testing compilation already uses more RAM (~5GB on 22 threads) than linking with parallelized LTO (~2.5GB on 22 threads, vs. ~0.2GB on 1 thread).

Outcomes

On an Intel Ultra 7 155H (16 cores/22 threads, up to 4.8 GHz), 32GB RAM, Fedora 44, GCC 16.0.1, this PR reduces linking time on iterative builds (single-cpp-file changes) with LTO enabled by about 75%, from 1m22s to 21s.

The same percentile reduction was reproduced on a Core i5-6500T (4 cores/4 threads, up to 2.7GHz), 32GB RAM, Fedora 43, GCC 15.2.1, from 2m29s to 0m47s on iterative builds. This suggests that improvements don't necessarily scale past 4 threads. On the 155H and -flto=4, the reduction was still about 62% (to 0m31).

There was no significant change in full clean compile build times between master, this PR (-flto=auto), -flto=4, and removing -flto. The improvements are entirely on iterative builds where

With -flto (master)

Full clean build, compilation and linking with debug symbols (~/git/daid/emptyepsilon-compile/ && rm -rf EmptyEpsilon/_build; cmake -S EmptyEpsilon -B EmptyEpsilon/_build -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo && time cmake --build EmptyEpsilon/_build) on the Ultra 7 155H/32GB RAM/F44/GCC 16:

real    1m20.968s
user    1m20.338s
sys     0m6.908s

Minor change, mostly linking

real    1m22.084s
user    1m17.553s
sys     0m3.496s

top shows load spread across all threads during compilation but concentrated on one thread during linking. Linking an iterative change alone takes almost as much time as a full recompilation with linking.

With -flto=auto (this PR)

Full clean build, compilation and linking

real    1m26.392s
user    22m2.587s
sys     2m8.504s

Minor change, mostly linking

real    0m21.196s
user    5m33.548s
sys     0m10.980s

top shows load spread across all threads during both compilation and linking. Linking an iterative change takes about 1/4 as long as a full recompilation.

With -flto removed (no optimization)

Full clean build, compilation and linking

real    1m25.206s
user    20m4.499s
sys     1m52.407s

Minor change, mostly linking

real    0m0.652s
user    0m0.448s
sys     0m0.200s

top shows load spread across all threads during compilation and is imperceptible during linking. Linking an iterative change without WPA or LTO takes almost no perceptible amount of time.

GCC 15 and 16 seem to default to using only 1 core when passing -flto,
so it handles each partition sequentially while the rest of the system
idles. GCC 10 and onward allow passing a number of threads as an option
to the flag (i.e. -flto=4) or auto to use all available.

Explicitly pass -flto=auto when compiling with GCC to ensure that it
parallelizes WPA and LTO.
@daid
daid merged commit 9a3958e into daid:master May 2, 2026
6 checks passed
oznogon added a commit to oznogon/SeriousProton that referenced this pull request May 2, 2026
GCC 15 and 16 seem to default to using only 1 core when passing -flto,
so it handles each partition sequentially while the rest of the system
idles. GCC 10 and onward allow passing a number of threads as an option
to the flag (i.e. -flto=4) or auto to use all available.

Explicitly pass -flto=auto when compiling with GCC to ensure that it
parallelizes WPA and LTO.
oznogon added a commit to oznogon/SeriousProton that referenced this pull request May 3, 2026
GCC 15 and 16 seem to default to using only 1 core when passing -flto,
so it handles each partition sequentially while the rest of the system
idles. GCC 10 and onward allow passing a number of threads as an option
to the flag (i.e. -flto=4) or auto to use all available.

Explicitly pass -flto=auto when compiling with GCC to ensure that it
parallelizes WPA and LTO.
@oznogon
oznogon deleted the parallelize-lto branch May 3, 2026 04:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants