Kompilasi dengan g ++ menggunakan multi core

174

Pertanyaan cepat: apa tanda kompiler yang memungkinkan g ++ untuk menelurkan banyak contoh dari dirinya sendiri untuk mengkompilasi proyek besar lebih cepat (misalnya 4 file sumber sekaligus untuk CPU multi-core)?

bsofman
sumber
Apakah ini akan sangat membantu? Semua pekerjaan kompilasi saya terikat I / O daripada terikat CPU.
Brian Knoblauch
5
Bahkan jika mereka terikat I / O Anda mungkin dapat menjaga beban I / O lebih tinggi ketika CPU bit berat terjadi (dengan hanya satu contoh g + + akan ada jeda) dan mungkin mendapatkan efisiensi I / O jika penjadwal memiliki lebih banyak pilihan tentang apa yang harus dibaca dari disk selanjutnya. Pengalaman saya adalah bahwa penggunaan yang bijaksana make -jhampir selalu menghasilkan beberapa perbaikan.
Flexo
1
@BrianKnoblauch Tetapi di komputer saya (yang asli atau di VirtualBox), itu terikat CPU, saya menemukan bahwa CPU sibuk melalui perintah 'top' ketika mengkompilasi.
大 宝剑
1
Bahkan jika mereka terikat I / O, kita dapat menggunakan flag '-pipa' gcc untuk mengurangi rasa sakit.
大 宝剑
baru saja melihat ini di google: gcc.gnu.org/onlinedocs/libstdc++/manual/…
Jim Michaels

Jawaban:

240

Anda dapat melakukan ini dengan make - dengan gnu make itu adalah flag -j (ini juga akan membantu pada mesin uniprocessor).

Misalnya jika Anda ingin 4 pekerjaan paralel dari make:

make -j 4

Anda juga dapat menjalankan gcc di dalam pipa dengan

gcc -pipe

Ini akan menyalurkan tahap kompilasi, yang juga akan membantu menjaga core tetap sibuk.

Jika Anda memiliki mesin tambahan juga tersedia, Anda mungkin memeriksa distcc , yang akan mengkompilasi juga untuk itu.

frankodwyer
sumber
36
Anda -j nomor harus 1,5x jumlah inti yang Anda miliki.
Mark Beckwith
2
Terima kasih. Saya terus mencoba meneruskan "-j #" ke gcc melalui CFLAGS / CPPFLAGS / CXXFLAGS. Saya benar-benar lupa bahwa "-j #" adalah parameter untuk GNU make (dan bukan untuk GCC).
chriv
33
Mengapa opsi- j untuk GNU Make harus berukuran 1,5 x jumlah core CPU?
bitek
28
Angka 1,5 adalah karena masalah ikatan I / O yang tercatat . Ini adalah aturan praktis. Sekitar 1/3 dari pekerjaan akan menunggu untuk I / O, sehingga pekerjaan yang tersisa akan menggunakan inti yang tersedia. Angka yang lebih besar dari inti lebih baik dan Anda bahkan bisa mencapai 2x . Lihat juga: Gnu membuat -jargumen
artless noise
4
@ Jimmichaels Bisa jadi karena dependensi buruk diatur dalam proyek Anda, (target mulai membangun bahkan jika dependensinya belum siap) sehingga hanya membangun berurutan akhirnya menjadi sukses.
Antonio
42

Tidak ada bendera seperti itu, dan memiliki satu berjalan bertentangan dengan filosofi Unix memiliki setiap alat melakukan hanya satu fungsi dan melakukannya dengan baik. Proses kompiler pemijahan secara konseptual adalah tugas sistem bangun. Apa yang mungkin Anda cari adalah bendera -j (pekerjaan) untuk GNU make, a la

make -j4

Atau Anda dapat menggunakan pmake atau sistem make paralel serupa.

Mihai Limbășan
sumber
3
"Unix pedantry tidak membantu" Untung saja itu bukan kesedihan, editor anonim. Diputar kembali. Peninjau harap lebih memperhatikan apa yang Anda lakukan.
Lightness Races in Orbit
12

Orang-orang telah menyebutkan maketetapi bjamjuga mendukung konsep serupa. Menggunakan bjam -jxmenginstruksikan bjam untuk membangun hingga xperintah bersamaan.

Kami menggunakan skrip build yang sama di Windows dan Linux dan menggunakan opsi ini membagi waktu build kami di kedua platform. Bagus.

MattyT
sumber
9

makeakan melakukan ini untukmu. Selidiki -jdan -laktifkan di halaman manual. Saya tidak berpikir g++dapat diparalelkan.

rmeador
sumber
+1 untuk -lopsi penyebutan (tidak memulai pekerjaan baru kecuali semua pekerjaan sebelumnya benar-benar berakhir). Kalau tidak, tampaknya pekerjaan linker dimulai dengan tidak semua file objek dibangun (karena beberapa kompilasi masih berlangsung), sehingga pekerjaan linker gagal.
NGI
8

Jika menggunakan make, masalah dengan -j. Dari 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.

Dan yang paling penting, jika Anda ingin membuat skrip atau mengidentifikasi jumlah inti yang Anda miliki (tergantung pada lingkungan Anda, dan jika Anda berjalan di banyak lingkungan, ini dapat banyak berubah) Anda dapat menggunakan fungsi Python di mana-mana cpu_count():

https://docs.python.org/3/library/multiprocessing.html#multiprocessing.cpu_count

Seperti ini:

make -j $(python3 -c 'import multiprocessing as mp; print(int(mp.cpu_count() * 1.5))')

Jika Anda bertanya mengapa 1.5saya akan mengutip suara bising pengguna dalam komentar di atas:

Angka 1,5 adalah karena masalah ikatan I / O yang tercatat. Ini adalah aturan praktis. Sekitar 1/3 dari pekerjaan akan menunggu untuk I / O, sehingga pekerjaan yang tersisa akan menggunakan inti yang tersedia. Angka yang lebih besar dari inti lebih baik dan Anda bahkan bisa mencapai 2x.

Havok
sumber
5
Sebagian besar pengguna Linux lebih suka yang lebih pendek: make -j`nproc` dengan nprocdi GNU Coreutils.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Jika Anda menggunakan SSD, I / O tidak akan menjadi masalah besar. Hanya untuk membangun komentar Ciro di atas, Anda dapat melakukan ini: make -j $(( $(nproc) + 1 ))(pastikan Anda meletakkan spasi di tempat saya memilikinya)
Ed K
Saran bagus menggunakan python, pada sistem nprocyang tidak tersedia, misalnya dalam manylinux1wadah, menghemat waktu tambahan dengan menghindari menjalankan yum update/ yum install.
hoefling
7

distcc juga dapat digunakan untuk mendistribusikan kompilasi tidak hanya pada mesin saat ini, tetapi juga pada mesin lain di pertanian yang memiliki distcc diinstal.

Jason
sumber
+1, distcc adalah alat yang berguna untuk dimiliki dalam gudang seseorang untuk bangunan besar.
Flexo
Sepertinya ada beberapa yang berfungsi "seperti" distcc juga: stackoverflow.com/questions/5374106/distributed-make/…
rogerdpack
3

Saya tidak yakin tentang g ++, tetapi jika Anda menggunakan GNU Make maka "make -j N" (di mana N adalah jumlah thread yang dapat dibuat buat) akan memungkinkan make untuk menjalankan pekerjaan multple g ++ secara bersamaan (begitu lama karena file tidak saling bergantung).

Andy
sumber
2
tidak, bukan jumlah utas! Banyak orang salah paham akan hal itu, tetapi -j Nmengatakan membuat berapa banyak proses sekaligus harus ditelurkan, bukan utas. Itulah alasan mengapa ia tidak sebagus MS cl -MT(benar-benar multithreaded).
Sebi2020
2

GNU paralel

Saya membuat tolok ukur kompilasi sintetis dan tidak mau repot untuk membuat Makefile, jadi saya menggunakan:

sudo apt-get install parallel
ls | grep -E '\.c$' | parallel -t --will-cite "gcc -c -o '{.}.o' '{}'"

Penjelasan:

  • {.} mengambil argumen input dan menghapus ekstensi
  • -t mencetak perintah yang sedang dijalankan untuk memberi kami gagasan tentang kemajuan
  • --will-cite menghapus permintaan untuk mengutip perangkat lunak jika Anda mempublikasikan hasil menggunakannya ...

parallel sangat nyaman sehingga saya bahkan dapat melakukan cap waktu sendiri:

ls | grep -E '\.c$' | parallel -t --will-cite "\
  if ! [ -f '{.}.o' ] || [ '{}' -nt '{.}.o' ]; then
    gcc -c -o '{.}.o' '{}'
  fi
"

xargs -Pjuga dapat menjalankan pekerjaan secara paralel, tetapi agak kurang nyaman untuk melakukan manipulasi ekstensi atau menjalankan beberapa perintah dengannya: Memanggil beberapa perintah melalui xargs

Penautan paralel ditanyakan di: Dapatkah gcc menggunakan banyak inti saat menautkan?

TODO: Saya pikir saya membaca di suatu tempat bahwa kompilasi dapat dikurangi menjadi perkalian matriks, jadi mungkin juga dimungkinkan untuk mempercepat kompilasi file tunggal untuk file besar. Tetapi saya tidak dapat menemukan referensi sekarang.

Diuji di Ubuntu 18.10.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
sumber