Compiling with g++ using multiple cores

172,969

Solution 1

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.

Solution 2

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.

Solution 3

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.

Solution 4

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.

Solution 5

make will do this for you. Investigate the -j and -l switches in the man page. I don't think g++ is parallelizable.

Share:
172,969

Related videos on Youtube

bsofman
Author by

bsofman

Updated on June 20, 2020

Comments

  • bsofman
    bsofman about 4 years

    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)?

    • user1568901
      user1568901 over 15 years
      Will it really help? All my compile jobs are I/O bound rather than CPU bound.
    • Flexo
      Flexo almost 13 years
      Even if they are I/O bound you can probably keep the I/O load higher when the CPU heavy bits are happening (with just one g++ instance there will be lulls) and possibly gain I/O efficiencies if the scheduler has more choice about what to read from disk next. My experience has been that judicious use of make -j almost always results in some improvement.
    • 大宝剑
      大宝剑 almost 11 years
      @BrianKnoblauch But on my machine(real one or in VirtualBox), it's CPU bound, I found that the CPU is busy through 'top' command when compiling.
    • 大宝剑
      大宝剑 almost 11 years
      Even if they are I/O bound, we can use gcc's flag '-pipe' to reduce pain.
    • Jim Michaels
      Jim Michaels about 10 years
    • underscore_d
      underscore_d almost 8 years
      @JimMichaels That's completely unrelated: it's about parallel processing as part of the program at runtime, i.e. after compilation. The question is about compiling in parallel using multiple jobs.
    • tofutim
      tofutim over 6 years
  • Mark Beckwith
    Mark Beckwith over 15 years
    You're -j number should be 1.5x the number of cores you have.
  • frankodwyer
    frankodwyer over 15 years
    yes, something like that makes sense given there is I/O as well - although may need some tuning if using -pipe as well
  • Flexo
    Flexo almost 13 years
    +1, distcc is a useful tool to have in one's arsenal for large builds.
  • chriv
    chriv over 11 years
    Thanks. I kept trying to pass "-j#" to gcc via CFLAGS/CPPFLAGS/CXXFLAGS. I had completely forgotten that "-j#" was a parameter for GNU make (and not for GCC).
  • Alex Bitek
    Alex Bitek over 11 years
    Why does the -j option for GNU Make needs to be 1.5 x the number of CPU cores?
  • artless noise
    artless noise almost 11 years
    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. See also: Gnu make -j arguments
  • rogerdpack
    rogerdpack almost 11 years
    Looks like there are a few that work "like" distcc as well: stackoverflow.com/questions/5374106/distributed-make/…
  • Jim Michaels
    Jim Michaels about 10 years
    make -j is broken, with mingw-w64 it will cause a long list of compilation errors whereas without project will compile fine. don't recommend it. I recommend submitting a bug report to the gnu make folk.
  • Jim Michaels
    Jim Michaels about 10 years
  • Piotr Kula
    Piotr Kula over 9 years
    Will the Raspberry Pi 2 benefit from this flag? Will it be able to compile faster thanks to the new 4 core processor?
  • Antonio
    Antonio about 9 years
    @JimMichaels It could be because dependencies are badly set within your project, (a target starts building even if its dependencies are not ready yet) so that only a sequential build ends up being successful.
  • Sebi2020
    Sebi2020 about 9 years
    no N ist not the number of threads! Many people misunderstand that, but -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).
  • Lightness Races in Orbit
    Lightness Races in Orbit about 8 years
    "Unix pedantry is not helpful" Good thing it wasn't pedantry then, anonymous editor. Rolled back. Reviewers please pay more attention to what you're doing.
  • Nick
    Nick over 7 years
    -pipe is not pipeline, its to use pipes instead of temporary files. Uses more memory, but in some cases is faster. If your project is large, it might be worth trying.
  • jjpe
    jjpe over 6 years
    Ok so this is quite a while after the original discussion, BUT: compiling Emacs git master on an AMD Threadripper 1950x with 16 cores using Fedora 27 completely breaks this 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...
  • NGI
    NGI almost 6 years
    +1 for mentioning -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.
  • Ciro Santilli OurBigBook.com
    Ciro Santilli OurBigBook.com over 5 years
    Most Linux users will likely prefer the shorter: make -j`nproc` with nproc in GNU Coreutils.
  • Ed K
    Ed K over 4 years
    If you're using an SSD, I/O isn't going to be as much of an issue. Just to build on Ciro's comment above, you can do this: make -j $(( $(nproc) + 1 )) (make sure you put spaces where I have them).
  • hoefling
    hoefling about 4 years
    Nice suggestion using python, on systems where nproc isn't available, e.g. in manylinux1 containers, it saves additional time by avoiding running yum update/yum install.
  • mercury0114
    mercury0114 over 3 years
    what happens if 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?
  • Spike0xff
    Spike0xff about 3 years
    despite the claim of non-pedantry, gcc is getting a flag -fparallel-jobs=N Better tell the GCC devs they're doing it wrong.