Birden fazla çekirdek kullanarak g ++ ile derleme


174

Kısa soru: g ++ 'ın büyük projeleri daha hızlı derlemek için kendisinin birden fazla örneğini üretmesine izin veren derleyici bayrağı nedir (örneğin, çok çekirdekli CPU için bir seferde 4 kaynak dosyası)?


Gerçekten yardımcı olacak mı? Tüm derleme işlerim CPU bağlı değil I / O bağlı.
Brian Knoblauch

5
I / O bağlı olsalar bile, CPU ağır bitleri meydana geldiğinde I / O yükünü daha yüksek tutabilirsiniz (sadece bir g ++ örneğiyle lull'lar olacaktır) ve zamanlayıcı daha fazla seçeneğe sahipse muhtemelen I / O verimliliği elde edebilirsiniz sonraki diskten ne okunacak. Deneyimlerime göre, make -jneredeyse her zaman akıllıca kullanılması bazı iyileştirmelerle sonuçlanmaktadır.
Flekso

1
@BrianKnoblauch Ama benim makinemde (gerçek bir veya VirtualBox), CPU bağlı, derlerken CPU 'top' komutu ile meşgul olduğunu buldum.
宝剑 宝剑

1
G / Ç bağlı olsalar bile, ağrıyı azaltmak için gcc'nin '-pipe' bayrağını kullanabiliriz.
宝剑 宝剑

Yanıtlar:


240

Bunu make ile yapabilirsiniz - gnu ile -j bayrağı yapmak (bu aynı zamanda bir tek işlemcili makinede yardımcı olacaktır).

Örneğin, 4 paralel işin yapılmasını istiyorsanız:

make -j 4

Ayrıca gcc'yi bir boruda

gcc -pipe

Bu, çekirdeklerin meşgul edilmesine yardımcı olacak derleme aşamalarını boru hattına bağlayacaktır.

Ek makineleriniz varsa, derlemeleri de bunlara ekleyecek distcc'ye göz atabilirsiniz .


36
-J sayınız sahip olduğunuz çekirdek sayısının 1,5 katı olmalıdır.
Mark Beckwith

2
Teşekkürler. CFLAGS / CPPFLAGS / CXXFLAGS üzerinden gcc'ye "-j #" iletmeye çalıştım. "-J #" ifadesinin GNU markası için bir parametre olduğunu tamamen unutmuştum (GCC için değil).
chriv

33
GNU Make için -j seçeneğinin neden CPU çekirdeği sayısının 1,5 katı olması gerekiyor?
bit

28
1.5 numara için belirtildiği ait G / Ç bağlı sorun. Bu bir kural. İşlerin yaklaşık 1 / 3'ü G / Ç'yi bekleyecek, bu nedenle kalan işler mevcut çekirdekleri kullanacaktır. Çekirdek daha çok sayıda büyük daha iyidir ve hatta olarak en yüksek olarak gidebiliriz 2x . Ayrıca bakınız: Gnu -jargümanlar yapıyor
sanatsız gürültü

4
@JimMichaels Bunun nedeni, bağımlılıkların projenizde kötü ayarlanmış olması olabilir (bağımlılıkları henüz hazır olmasa bile bir hedef oluşturmaya başlar), böylece yalnızca sıralı bir yapı başarılı olur.
Antonio

42

Böyle bir bayrak yoktur ve her aracın sadece bir işlevi yerine getirmesini ve iyi çalışmasını sağlamak için Unix felsefesine karşı bir tane çalıştırmaktır. Derleyici işlemlerini yumurtlama kavramsal olarak yapı sisteminin görevidir. Muhtemelen aradığınız şey, GNU markasına -j (iş) bayrağı,

-j4 yap

Veya pmake veya benzeri paralel markalama sistemleri kullanabilirsiniz.



3
"Unix bilgiçlik işe yaramaz " O zaman bilgelik değildi iyi bir şey, anonim editör. Geri alındı. Gözden geçirenler lütfen ne yaptığınıza daha fazla dikkat edin.
Yörüngedeki Hafiflik Yarışları

12

İnsanlar da benzer bir kavramdan bahsetmiş makeancak bjamdesteklemiştir. Kullanarak bjam -jxbjam xkomutunu eşzamanlı komutlar oluşturmaya yönlendirir .

Windows ve Linux'ta aynı derleme komut dosyalarını kullanıyoruz ve bu seçeneği kullanmak her iki platformdaki derleme sürelerimizi yarıya indiriyor. Güzel.


9

makebunu sizin için yapacak. Kılavuz sayfasındaki -jve -ldüğmelerini araştırın . g++Paralel olabileceğini düşünmüyorum .


Bahsetme -lseçeneği için +1 (önceki tüm işler sona ermedikçe yeni bir iş başlatmaz). Aksi takdirde, linker işi, inşa edilen tüm nesne dosyalarıyla (bazı derlemeler hala devam ettiği için) başlar, böylece linker işi başarısız olur.
NGI

8

Make kullanıyorsanız ile sorun -j. Gönderen 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.

Ve en önemlisi, elinizdeki çekirdek sayısını kodlamak veya tanımlamak istiyorsanız (ortamınıza bağlı olarak ve birçok ortamda çalıştırıyorsanız, bu çok değişebilir) her yerde bulunan Python işlevini kullanabilirsiniz cpu_count():

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

Bunun gibi:

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

1.5Yukarıdaki yorumda neden kullanıcıya artless gürültü teklif edeceğimi soruyorsanız :

1.5 sayısı, belirtilen G / Ç bağlı probleminden kaynaklanmaktadır. Bu bir kural. İşlerin yaklaşık 1 / 3'ü G / Ç'yi bekleyecek, bu nedenle kalan işler mevcut çekirdekleri kullanacaktır. Çekirdeklerden daha büyük bir sayı daha iyidir ve hatta 2x'e kadar çıkabilirsiniz.


5
Çoğu Linux kullanıcıları olasılıkla daha kısa tercih edecektir: make -j`nproc` ile nprocGNU coreutils içerisinde.
Ciro Santilli 法轮功 冠状 病 六四 事件 法轮功

Bir SSD kullanıyorsanız, G / Ç bir sorun olmayacaktır. Sadece Ciro'nun yorumuna dayanmak için bunu yapabilirsiniz: make -j $(( $(nproc) + 1 ))(sahip olduğum yere boşluk bıraktığınızdan emin olun).
Ed K

Sistemlerde Python kullanılarak Güzel öneri, nprocmevcut değildir, örneğin içinde manylinux1konteynerler, Çalışıyorsa kaçınarak ek süre kazandırır yum update/ yum install.
Hoefling


3

G ++ hakkında emin değilim, ancak GNU Make kullanıyorsanız "make -j N" (burada N, oluşturduğu iş parçacığı sayısıdır) aynı anda (çok uzun süre) birden fazla g ++ işini çalıştırmaya izin verecektir çünkü dosyalar birbirine bağlı değildir).


2
hayır Konu sayısı değil! Birçok insan bunu yanlış anlıyor, ancak -j Naynı anda kaç işlemin ortaya çıkacağını söylüyor, iş parçacıkları değil. Bu nedenle MS kadar performans göstermemesinin nedeni cl -MT(gerçekten çok iş parçacıklı).
Sebi2020

2

GNU paralel

Sentetik bir derleme ölçütü yapıyordum ve bir Makefile yazmak için rahatsız edilemedim, bu yüzden kullandım:

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

Açıklama:

  • {.} girdi bağımsız değişkenini alır ve uzantısını kaldırır
  • -t bize ilerleme hakkında fikir vermek için çalıştırılan komutları yazdırır
  • --will-cite sonuçları kullanarak yayınlarsanız yazılımdan alıntı yapma isteğini kaldırır ...

parallel kendimi kontrol etmek için bir zaman damgası bile yapabilirim:

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

xargs -Pişleri paralel olarak da çalıştırabilir, ancak uzantı manipülasyonunu yapmak veya onunla birden fazla komut çalıştırmak biraz daha az uygundur: xargs üzerinden birden fazla komutu çağırmak

Paralel bağlama şu adresten soruldu: gcc, bağlantı yaparken birden fazla çekirdek kullanabilir mi?

YAPILACAKLAR: Ben derleme matris çarpımı azaltılabilir bir yerde okumak düşünüyorum, bu yüzden belki de büyük dosyalar için tek dosya derleme hızlandırmak mümkündür. Ama şimdi referans bulamıyorum.

Ubuntu 18.10'da test edilmiştir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.