Quick question: what is the compiler flag to allow g++ to spawn multiple instances of itself in order to compile large projects quicker (for example 4 source files at a time for a multi-core CPU)?
You can do this with make - with gnu make it is the -j flag (this will also help on a uniprocessor machine).
For example if you want 4 parallel jobs from make:
make -j 4
You can also run gcc in a pipe with
gcc -pipe
This will pipeline the compile stages, which will also help keep the cores busy.
If you have additional machines available too, you might check out distcc, which will farm compiles out to those as well.
-j
arguments –
Vampire 1.5x
rule of thumb. There are 32 threads available, and 16 physical cores, yet make -j 12
is roughly fastest with approximately 1m15
to 1m20
user time. Increasing the arg to -j
only increases build times. So in effect it's more like 3/4 x
or 3/8 x
depending on whether you want to count SMT "cores" or not. Of course it's entirely possible here that TR just rips through the parallellizable parts quickly... –
Lith make test
? –
Hymnody There is no such flag, and having one runs against the Unix philosophy of having each tool perform just one function and perform it well. Spawning compiler processes is conceptually the job of the build system. What you are probably looking for is the -j (jobs) flag to GNU make, a la
make -j4
Or you can use pmake or similar parallel make systems.
If using make, issue with -j
. From man make
:
-j [jobs], --jobs[=jobs] Specifies the number of jobs (commands) to run simultaneously. If there is more than one -j option, the last one is effective. If the -j option is given without an argument, make will not limit the number of jobs that can run simultaneously.
And most notably, if you want to script or identify the number of cores you have available (depending on your environment, and if you run in many environments, this can change a lot) you may use ubiquitous Python function cpu_count()
:
https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count
Like this:
make -j $(python3 -c 'import multiprocessing as mp; print(int(mp.cpu_count() * 1.5))')
If you're asking why 1.5
I'll quote user artless-noise in a comment above:
The 1.5 number is because of the noted I/O bound problem. It is a rule of thumb. About 1/3 of the jobs will be waiting for I/O, so the remaining jobs will be using the available cores. A number greater than the cores is better and you could even go as high as 2x.
make -j`nproc`
with nproc
in GNU Coreutils. –
Tartuffe make -j $(( $(nproc) + 1 ))
(make sure you put spaces where I have them). –
Gait nproc
isn't available, e.g. in manylinux1
containers, it saves additional time by avoiding running yum update
/yum install
. –
Mcgruder make
will do this for you. Investigate the -j
and -l
switches in the man page. I don't think g++
is parallelizable.
-l
option ( does not start a new job unless all previous jobs did terminate ). Otherwise it seems that the linker job begins with not all object files built (as some compilations are still ongoing), so that the linker job fails. –
Irrupt People have mentioned make
but bjam
also supports a similar concept. Using bjam -jx
instructs bjam to build up to x
concurrent commands.
We use the same build scripts on Windows and Linux and using this option halves our build times on both platforms. Nice.
distcc can also be used to distribute compiles not only on the current machine, but also on other machines in a farm that have distcc installed.
You can use make -j$(nproc)
. This command is used to build a project using the make build system with multiple jobs running in parallel.
For example, if your system has 4 CPU cores, running make -j$(nproc)
would instruct make to run 4 jobs concurrently, one on each CPU core, speeding up the build process.
You can also see how many cores you have with run this command;
echo $(nproc)
nproc
doesn't always yield optimal performance. My machine has four cores but compilation runs faster with -j2. –
Stableboy I'm not sure about g++, but if you're using GNU Make then "make -j N" (where N is the number of threads make can create) will allow make to run multple g++ jobs at the same time (so long as the files do not depend on each other).
-j N
tells make how many processes at once should be spawned, not threads. That's the reason why it is not as performant as MS cl -MT
(really multithreaded). –
Thankless N
is too large? E.g. can -j 100
break the system or is N
merely an upper bound that is not required to achieve? –
Carven GNU parallel
I was making a synthetic compilation benchmark and couldn't be bothered to write a Makefile, so I used:
sudo apt-get install parallel
ls | grep -E '\.c$' | parallel -t --will-cite "gcc -c -o '{.}.o' '{}'"
Explanation:
{.}
takes the input argument and removes its extension-t
prints out the commands being run to give us an idea of progress--will-cite
removes the request to cite the software if you publish results using it...
parallel
is so convenient that I could even do a timestamp check myself:
ls | grep -E '\.c$' | parallel -t --will-cite "\
if ! [ -f '{.}.o' ] || [ '{}' -nt '{.}.o' ]; then
gcc -c -o '{.}.o' '{}'
fi
"
xargs -P
can also run jobs in parallel, but it is a bit less convenient to do the extension manipulation or run multiple commands with it: Calling multiple commands through xargs
Parallel linking was asked at: Can gcc use multiple cores when linking?
TODO: I think I read somewhere that compilation can be reduced to matrix multiplication, so maybe it is also possible to speed up single file compilation for large files. But I can't find a reference now.
Tested in Ubuntu 18.10.
© 2022 - 2024 — McMap. All rights reserved.
make -j
almost always results in some improvement. – Bradway