รวบรวมด้วย g ++ โดยใช้หลายแกน


174

คำถามด่วน: ธงคอมไพเลอร์คืออะไรที่อนุญาตให้ g ++ วางไข่หลายอินสแตนซ์ของตัวเองเพื่อรวบรวมโครงการขนาดใหญ่ได้เร็วขึ้น (เช่นไฟล์ต้นฉบับ 4 ไฟล์ในเวลาเดียวกันสำหรับ CPU แบบมัลติคอร์)?


มันจะช่วยได้จริงเหรอ? งานรวบรวมทั้งหมดของฉันคือ I / O ที่ถูกผูกไว้แทนที่จะเป็น CPU ที่ถูกผูกไว้
Brian Knoblauch

5
แม้ว่าจะเป็น I / O ที่ถูกผูกไว้คุณก็สามารถทำให้โหลด I / O สูงขึ้นได้เมื่อ CPU ที่มีบิตหนักเกิดขึ้น (โดยมีเพียงหนึ่ง g ++ อินสแตนซ์จะมีเพลงกล่อมเด็ก) และอาจได้รับประสิทธิภาพ I / O หากตารางเวลามีตัวเลือกมากขึ้น สิ่งที่ต้องอ่านจากดิสก์ต่อไป ประสบการณ์ของฉันคือการใช้ความรอบคอบอย่างรอบคอบmake -jเกือบทุกครั้งจะทำให้เกิดการปรับปรุง
เฟล็กโซ

1
@BrianKnoblauch แต่ในเครื่องของฉัน (ของจริงหรือใน VirtualBox) มันเป็น CPU ที่ถูกผูกไว้ฉันพบว่า CPU ไม่ว่างผ่านคำสั่ง 'top' เมื่อรวบรวม
大宝剑

1
แม้ว่าพวกเขาจะถูกผูกไว้ I / O เราสามารถใช้ธงของ gcc '-pipe' เพื่อลดความเจ็บปวด
大宝剑

เพิ่งเห็นสิ่งนี้ใน google: gcc.gnu.org/onlinedocs/libstdc++/manual/…
Jim Michaels

คำตอบ:


240

คุณสามารถทำได้ด้วย make - ด้วย gnu ทำให้เป็นแฟล็ก -j (สิ่งนี้จะช่วยในเครื่องตัวประมวลผลเดียว)

ตัวอย่างเช่นถ้าคุณต้องการให้ 4 งานแบบขนานจาก make:

make -j 4

คุณยังสามารถเรียกใช้ gcc ในไปป์ด้วย

gcc -pipe

ขั้นตอนนี้จะเป็นการรวบรวมขั้นตอนการคอมไพล์ซึ่งจะช่วยให้แกนไม่ว่าง

หากคุณมีเครื่องจักรเพิ่มเติมด้วยเช่นกันคุณอาจตรวจสอบdistccซึ่งฟาร์มจะรวบรวมข้อมูลเหล่านั้นเช่นกัน


36
คุณคือ -j number ควรเป็น 1.5x ตามจำนวน cores ที่คุณมี
Mark Beckwith

2
ขอบคุณ ฉันพยายามส่ง "-j #" ไปยัง gcc ผ่านทาง CFLAGS / CPPFLAGS / CXXFLAGS ฉันลืมไปอย่างสมบูรณ์ว่า "-j #" เป็นพารามิเตอร์สำหรับ GNU make (ไม่ใช่สำหรับ GCC)
chriv

33
ทำไมตัวเลือก-jสำหรับ GNU Make จึงต้องมีจำนวนแกน CPU ถึง 1.5 เท่า
bitek

28
1.5จำนวนเป็นเพราะการตั้งข้อสังเกตของ I / O ที่ถูกผูกไว้ปัญหา มันเป็นกฎง่ายๆ ประมาณ 1/3 ของงานที่จะรอ I / O ดังนั้นงานที่เหลือจะใช้แกนที่มีอยู่ จำนวนมากกว่าแกนจะดีกว่าและคุณยังสามารถไปได้สูงถึง2 เท่า ดูเพิ่มเติมที่: Gnu ทำการ-jโต้แย้ง
เสียงอึกทึกครึกครื้น

4
@JimMichaels อาจเป็นเพราะการอ้างอิงถูกตั้งค่าไว้ไม่ดีในโครงการของคุณ (เป้าหมายเริ่มสร้างแม้ว่าการขึ้นต่อกันของมันจะยังไม่พร้อม) ดังนั้นการสร้างแบบต่อเนื่องจะประสบความสำเร็จ
อันโตนิโอ

42

ไม่มีการตั้งค่าสถานะดังกล่าวและมีหนึ่งทำงานกับปรัชญา Unix ของการมีเครื่องมือแต่ละตัวทำงานเพียงหนึ่งฟังก์ชั่นและทำงานได้ดี กระบวนการคอมไพเลอร์วางไข่เป็นแนวคิดงานของระบบสร้าง สิ่งที่คุณกำลังมองหาคือการตั้งค่าสถานะ -j (งาน) เพื่อ GNU, a la

ทำ -j4

หรือคุณสามารถใช้ pmake หรือระบบสร้างขนานที่คล้ายกัน



3
"อวดรู้ Unix ไม่เป็นประโยชน์"สิ่งที่ดีมันไม่อวดรู้เลยบรรณาธิการไม่ระบุชื่อ ย้อนกลับ ผู้ตรวจสอบโปรดให้ความสำคัญกับสิ่งที่คุณทำ
การแข่งขัน Lightness ใน Orbit

12

ผู้คนได้กล่าวถึงmakeแต่bjamยังสนับสนุนแนวคิดที่คล้ายกัน การใช้bjam -jxสั่งให้ bjam สร้างxคำสั่งพร้อมกัน

เราใช้สคริปต์การสร้างเดียวกันบน Windows และ Linux และการใช้ตัวเลือกนี้จะลดเวลาการสร้างของเราลงทั้งสองแพลตฟอร์ม ดี


9

makeจะทำสิ่งนี้เพื่อคุณ ตรวจสอบ-jและ-lสลับในหน้าคน ฉันไม่คิดว่าg++มันขนานกันได้


+1 สำหรับ-lตัวเลือกการกล่าวถึง(ไม่เริ่มงานใหม่เว้นแต่งานก่อนหน้านี้ทั้งหมดยุติลง) มิฉะนั้นดูเหมือนว่างานตัวลิงก์เริ่มต้นด้วยไม่ใช่วัตถุไฟล์ทั้งหมดที่สร้างขึ้น (เนื่องจากการรวบรวมบางส่วนยังคงดำเนินต่อไป) เพื่อให้งานตัวเชื่อมโยงล้มเหลว
NGI

8

-jถ้าใช้ทำให้ปัญหากับ จาก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.

และที่สำคัญที่สุดคือถ้าคุณต้องการเขียนสคริปต์หรือระบุจำนวนแกนประมวลผลที่คุณมีอยู่ (ขึ้นอยู่กับสภาพแวดล้อมของคุณและหากคุณใช้งานในหลาย ๆ สภาพแวดล้อมสิ่งนี้สามารถเปลี่ยนแปลงได้มากมาย) คุณอาจใช้ฟังก์ชัน Python ทั่วไปcpu_count():

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

แบบนี้:

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

หากคุณกำลังถามว่าทำไม1.5ฉันจะพูดผู้ใช้ไร้เสียงในความคิดเห็นข้างต้น:

หมายเลข 1.5 เป็นเพราะปัญหาการผูก I / O ที่บันทึกไว้ มันเป็นกฎง่ายๆ ประมาณ 1/3 ของงานที่จะรอ I / O ดังนั้นงานที่เหลือจะใช้แกนที่มีอยู่ จำนวนที่มากกว่าคอร์นั้นดีกว่าและคุณสามารถสูงได้ถึง 2x


5
ผู้ใช้ลินุกซ์ส่วนใหญ่มีแนวโน้มที่จะชอบสั้น: make -j`nproc` กับnprocใน GNU coreutils
Ciro Santilli 郝海东冠状病六四事件法轮功

หากคุณใช้ SSD I / O จะไม่เป็นปัญหามากนัก เพียงเพื่อสร้างความคิดเห็นของ Ciro ด้านบนคุณสามารถทำได้: make -j $(( $(nproc) + 1 ))(ตรวจสอบให้แน่ใจว่าคุณใส่ช่องว่างที่ฉันมี)
Ed K

ข้อเสนอแนะที่ดีโดยใช้หลามในระบบที่nprocไม่สามารถใช้ได้เช่นในmanylinux1ภาชนะบรรจุที่มันจะช่วยประหยัดเวลาเพิ่มเติมโดยการหลีกเลี่ยงการทำงาน/yum update yum install
hoefling

7

distcc สามารถใช้เพื่อแจกจ่ายคอมไพล์ไม่เพียง แต่ในเครื่องปัจจุบัน แต่ยังสามารถใช้กับเครื่องอื่น ๆ ในฟาร์มที่ติดตั้ง distcc


+1, distcc เป็นเครื่องมือที่มีประโยชน์สำหรับคลังแสงขนาดใหญ่
เฟล็กโซ

ดูเหมือนว่ามีบางอย่างที่ทำงาน "ชอบ" distcc เช่นกัน: stackoverflow.com/questions/5374106/distributed-make/…
rogerdpack

3

ฉันไม่แน่ใจเกี่ยวกับ g ++ แต่ถ้าคุณใช้ GNU Make แล้ว "make -j N" (โดยที่ N คือจำนวนเธรดที่สามารถสร้างได้) จะอนุญาตให้ make รันงาน multple g ++ ในเวลาเดียวกัน (นานมาก เนื่องจากไฟล์ไม่ได้ขึ้นอยู่กับแต่ละไฟล์)


2
no N ไม่ใช่จำนวนของเธรด! หลายคนเข้าใจผิดว่า แต่-j Nบอกให้ทำจำนวนกระบวนการในครั้งเดียวควรจะเกิดขึ้นไม่ใช่หัวข้อ นั่นเป็นเหตุผลว่าทำไมมันจึงไม่เป็นเช่นเดียวกับ MS cl -MT(มัลติเธรดจริงๆ)
Sebi2020

2

GNU ขนาน

ฉันสร้างมาตรฐานการรวบรวมสังเคราะห์และไม่สามารถใส่ใจในการเขียน Makefile ดังนั้นฉันจึงใช้:

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

คำอธิบาย:

  • {.} รับอาร์กิวเมนต์อินพุตและลบส่วนขยาย
  • -t พิมพ์คำสั่งที่กำลังทำงานอยู่เพื่อแจ้งให้เราทราบถึงความคืบหน้า
  • --will-cite ลบคำขอเพื่ออ้างอิงซอฟต์แวร์หากคุณเผยแพร่ผลลัพธ์โดยใช้ ...

parallel สะดวกมากที่ฉันสามารถตรวจสอบเวลาได้ด้วยตนเอง:

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

xargs -Pยังสามารถเรียกใช้งานแบบขนาน แต่มันสะดวกน้อยกว่าเล็กน้อยในการจัดการส่วนขยายหรือเรียกใช้หลายคำสั่งด้วยการเรียกคำสั่งหลายคำสั่งผ่าน xargs

มีการถามการเชื่อมโยงแบบขนานที่: gcc สามารถใช้หลายคอร์เมื่อเชื่อมโยง

สิ่งที่ต้องทำ: ฉันคิดว่าฉันอ่านที่ไหนสักแห่งว่าการรวบรวมสามารถลดการคูณเมทริกซ์ดังนั้นอาจเป็นไปได้ที่จะเพิ่มความเร็วในการรวบรวมไฟล์เดียวสำหรับไฟล์ขนาดใหญ่ แต่ตอนนี้ฉันไม่สามารถหาข้อมูลอ้างอิงได้

ทดสอบใน Ubuntu 18.10

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.