เสียงดังก้องกับ GCC - ซึ่งสร้างไบนารีที่ดีกว่า? [ปิด]


238

ปัจจุบันฉันใช้ GCC แต่ฉันค้นพบ Clang เมื่อเร็ว ๆ นี้และฉันกำลังไตร่ตรองการสลับ มีปัจจัยหนึ่งในการตัดสินใจว่า - คุณภาพ (ความเร็ว, หน่วยความจำรอยเท้า, ความน่าเชื่อถือ) ของไบนารีที่สร้าง - หากgcc -O3สามารถสร้างไบนารีที่ทำงานได้เร็วขึ้น 1% หรือใช้หน่วยความจำน้อยลง 1% มันเป็นดีลเลอร์ดีล

Clang มีความเร็วในการคอมไพล์ที่ดีขึ้นและการปล่อยหน่วยความจำเวลาคอมไพล์ที่ต่ำกว่า GCC แต่ฉันสนใจในการวัด / เปรียบเทียบผลของซอฟต์แวร์ที่คอมไพล์แล้ว - คุณช่วยชี้ให้ฉันเห็นหรือเล่าประสบการณ์ของคุณได้ไหม?


5
ดูเหมือนว่ายังเป็นคำถามและคำตอบที่มีค่าและหลายคนสนใจ
YasserAsmi

9
@ YasserAsmi: และทั้งสองตัวชี้วัด - รอยเท้าหน่วยความจำและความเร็วในการดำเนินการ - อยู่ไกลจากการสุ่มหรืออาจมีการ "ความคิดเห็น" แต่ดูเหมือนว่าโรคของ Physics.SE จะแพร่กระจายไปที่นี่และผู้คนก็เริ่มลงคะแนนให้ปิดโดยไม่ต้องอ่านรายละเอียดข้อความคำถามที่นี่เช่นกัน
เอสเอฟ

12
คำถามถามหามาตรฐานและการเปรียบเทียบคำตอบให้ทั้งสอง ... ทำไมความคิดเห็นนี้จึงไม่ใช่การเปรียบเทียบจริง
oemb1905

2
ไม่เห็นว่าทำไมคำถามนี้จึงปิด ไม่ว่าจะเป็นความคิดเห็นหรือตามข้อเท็จจริงเราต้องการทราบคำตอบและการทำเครื่องหมายเป็นปิดจะทำให้ได้สีที่ไม่ดี
Timothy Makobu

2
@ TomZych: หากคุณต้องการทราบปัจจัยเหล่านี้ให้ถามคำถามที่แตกต่าง อันนี้มีความเฉพาะเจาะจงและชัดเจนมาก - ขอความเร็วในการทำงานและการปล่อยหน่วยความจำ คุณอาจสนใจในปัจจัยอื่น ๆ ที่ดีสำหรับคุณที่ไม่ได้หมายความว่าคำถามนี้ไม่ถูกต้อง แต่ก็ไม่ตรงกับความสนใจส่วนตัวของคุณ มันเหมือนกับว่าคุณเป็นโปรแกรมเมอร์ Java และต้องการปิดคำถาม C # ทุกคำถามเพราะไม่ได้พูดถึง Java
เอสเอฟ

คำตอบ:


239

นี่คือบางส่วนที่ทันสมัยแม้ว่าจะมีการค้นพบที่แคบของ GCC 4.7.2 และ Clang 3.2 สำหรับ C ++

อัปเดต: GCC 4.8.1 v เสียงดังกังวาน 3.3 เปรียบเทียบผนวกท้ายด้านล่าง

อัปเดต: GCC 4.8.2 v clang 3.4 การเปรียบเทียบจะถูกต่อท้าย

ฉันบำรุงรักษาเครื่องมือ OSS ที่สร้างขึ้นสำหรับ Linux กับทั้ง GCC และ Clang และด้วยคอมไพเลอร์ของ Microsoft สำหรับ Windows เครื่องมือ coan เป็นตัวประมวลผลล่วงหน้าและตัววิเคราะห์ของซอร์สไฟล์ C / C ++ และ codelines ของเช่น: เมเจอร์โปรไฟล์การคำนวณบนการแยกวิเคราะห์แบบเรียกซ้ำและการจัดการไฟล์ สาขาการพัฒนา (ซึ่งเกี่ยวข้องกับผลลัพธ์เหล่านี้) ประกอบด้วยปัจจุบันประมาณ 11K LOC ในประมาณ 90 ไฟล์ มันถูกเข้ารหัสแล้วตอนนี้ใน C ++ ที่อุดมไปด้วย polymorphism และ template และยังคงติดอยู่ใน patch จำนวนมากโดยที่ผ่านมาไม่ไกลในการแฮ็คเข้าด้วยกัน C. ความหมายของการย้ายไม่ได้ถูกใช้ประโยชน์อย่างชัดเจน มันเป็นเธรดเดียว ฉันไม่ได้ใช้ความพยายามอย่างจริงจังเพื่อเพิ่มประสิทธิภาพในขณะที่ "สถาปัตยกรรม" ยังคงเป็นสิ่งที่ต้องทำส่วนใหญ่

ฉันจ้าง Clang ก่อนหน้านี้เพียง 3.2 เป็นคอมไพเลอร์ทดลองเพราะถึงแม้จะมีความเร็วในการรวบรวมและการวินิจฉัยที่เหนือกว่า แต่การสนับสนุนมาตรฐาน C ++ 11 นั้นทำให้เวอร์ชัน GCC ร่วมสมัยล่าช้ากว่ารุ่น GCC ที่ใช้ร่วมกัน ด้วย 3.2 ทำให้ช่องว่างนี้ถูกปิด

ชุดทดสอบลินุกซ์ของฉันสำหรับกระบวนการพัฒนา coan ปัจจุบันโดยประมาณ 70K แหล่งไฟล์ในส่วนผสมของ parser หนึ่งไฟล์กรณีทดสอบความเครียดทดสอบการบริโภค 1000s ของไฟล์และการทดสอบสถานการณ์การใช้ไฟล์ <1K เช่นเดียวกับการรายงานผลการทดสอบ harness จะสะสมและแสดงผลรวมของไฟล์ที่ใช้ไปและเวลาที่ใช้ไปใน coan (มันจะผ่านแต่ละบรรทัดคำสั่ง coan ไปยังtimeคำสั่งLinux และรวบรวมและเพิ่มตัวเลขที่รายงาน) การกำหนดเวลามีความภูมิใจเนื่องจากความจริงที่ว่าจำนวนการทดสอบใด ๆ ที่ใช้เวลา 0 ที่สามารถวัดได้จะเพิ่มขึ้นเป็น 0 แต่การมีส่วนร่วมของการทดสอบดังกล่าวนั้นเล็กน้อย สถิติเวลาจะปรากฏที่ส่วนท้ายของmake checkสิ่งนี้:

coan_test_timer: info: coan processed 70844 input_files.
coan_test_timer: info: run time in coan: 16.4 secs.
coan_test_timer: info: Average processing time per input file: 0.000231 secs.

ฉันเปรียบเทียบประสิทธิภาพของชุดทดสอบทดสอบระหว่าง GCC 4.7.2 และ Clang 3.2 ทุกสิ่งเท่าเทียมกันโดยไม่รวมคอมไพเลอร์ ตั้งแต่ Clang 3.2 ฉันไม่ต้องการการแยกความแตกต่างระหว่าง preprocessor ของโค้ดที่ GCC จะรวบรวมและทางเลือก Clang ฉันสร้างไลบรารี C ++ เดียวกัน (GCC) ในแต่ละกรณีและทำการเปรียบเทียบทั้งหมดอย่างต่อเนื่องในเซสชันเทอร์มินัลเดียวกัน

ระดับการปรับให้เหมาะสมเริ่มต้นสำหรับ build build ของฉันคือ -O2 ฉันทดสอบการสร้างได้สำเร็จที่ -O3 ฉันทดสอบการกำหนดค่าแต่ละครั้ง 3 ครั้งย้อนกลับไปด้านหลังและเฉลี่ยผลลัพธ์ 3 รายการด้วยผลลัพธ์ต่อไปนี้ หมายเลขในเซลล์ข้อมูลคือจำนวนไมโครวินาทีโดยเฉลี่ยที่ใช้โดย coan ที่สามารถประมวลผลเพื่อประมวลผลไฟล์อินพุต ~ 70K แต่ละไฟล์ (อ่าน, แยกวิเคราะห์และเขียนเอาต์พุตและวินิจฉัย)

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 231 | 237 |0.97 |
----------|-----|-----|-----|
Clang-3.2 | 234 | 186 |1.25 |
----------|-----|-----|------
GCC/Clang |0.99 | 1.27|

แอปพลิเคชันใด ๆ โดยเฉพาะมีแนวโน้มที่จะมีลักษณะที่เล่นอย่างไม่ยุติธรรมต่อจุดแข็งหรือจุดอ่อนของคอมไพเลอร์ การเปรียบเทียบที่เข้มงวดมีการใช้งานที่หลากหลาย เมื่อคำนึงถึงคุณสมบัติของข้อมูลเหล่านี้แล้ว:

  1. การเพิ่มประสิทธิภาพ -O3 เป็นอันตรายต่อ GCC
  2. -O3 optimization นั้นสำคัญต่อ Clang
  3. ที่ -O2 optimization GCC นั้นเร็วกว่า Clang เพียงแค่มัสสุ
  4. ที่ -O3 optimization Clang สำคัญกว่า GCC

การเปรียบเทียบที่น่าสนใจต่อไปของคอมไพเลอร์ทั้งสองเกิดขึ้นโดยบังเอิญหลังจากการค้นพบเหล่านั้น Coan เปิดตัวสมาร์ทพอยน์เตอร์อย่างชาญฉลาดและหนึ่งในนั้นถูกใช้อย่างหนักในการจัดการไฟล์ โดยเฉพาะอย่างยิ่งประเภทสมาร์ทชี้นี้ได้รับการ typedef'd ในรุ่นก่อนเพื่อประโยชน์ของคอมไพเลอร์-ความแตกต่างที่จะเป็นฝ่ายสนับสนุนถ้าคอมไพเลอร์ที่กำหนดค่าได้พอสุกสำหรับการใช้งานของมันเช่นนั้นและมิฉะนั้นstd::unique_ptr<X> std::shared_ptr<X>ความลำเอียงที่std::unique_ptrเป็นเรื่องโง่เง่าเนื่องจากพอยน์เตอร์เหล่านี้ถูกถ่ายโอนไปรอบ ๆ แต่std::unique_ptrดูเหมือนว่าตัวเลือกที่เหมาะสมสำหรับการแทนที่ std::auto_ptrณ จุดหนึ่งเมื่อตัวแปร C ++ 11 เป็นนวนิยายสำหรับฉัน

ในระหว่างการทดลองสร้างเพื่อวัดความต้องการอย่างต่อเนื่องของ Clang 3.2 สำหรับสิ่งนี้และความแตกต่างที่คล้ายกันฉันสร้างขึ้นโดยไม่ตั้งใจ std::shared_ptr<X>เมื่อฉันตั้งใจจะสร้างstd::unique_ptr<X>และรู้สึกประหลาดใจที่สังเกตเห็นว่าปฏิบัติการที่เกิดขึ้น เคยเห็นบางครั้งสามารถบรรลุ 184 มิลลิเซคอน ต่อไฟล์อินพุต เมื่อสิ่งนี้เปลี่ยนเป็นซอร์สโค้ดผลลัพธ์ที่ตรงกันก็คือสิ่งเหล่านี้

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.7.2 | 234 | 234 |1.00 |
----------|-----|-----|-----|
Clang-3.2 | 188 | 187 |1.00 |
----------|-----|-----|------
GCC/Clang |1.24 |1.25 |

จุดที่ควรทราบคือ:

  1. คอมไพเลอร์ไม่ได้ประโยชน์จากการปรับให้เหมาะสม -O3
  2. เสียงดังกังวานเต้น GCC เช่นเดียวกับที่สำคัญในการเพิ่มประสิทธิภาพในแต่ละระดับ
  3. ประสิทธิภาพของ GCC นั้นได้รับผลกระทบเพียงเล็กน้อยจากการเปลี่ยนแปลงประเภทตัวชี้อัจฉริยะ
  4. ประสิทธิภาพของ Clang -O2 นั้นได้รับผลกระทบจากการเปลี่ยนชนิดตัวชี้สมาร์ท

ก่อนและหลังการเปลี่ยนชนิดตัวชี้สมาร์ทเสียงดังกังวานสามารถสร้างความสามารถในการประมวลผลได้เร็วขึ้นอย่างมากที่ -O3 และมันสามารถสร้างความสามารถในการปฏิบัติการที่รวดเร็วกว่าที่ -O2 และ -O3 เมื่อตัวชี้ประเภทนั้นดีที่สุดstd::shared_ptr<X>- สำหรับงาน

คำถามที่ชัดเจนว่าฉันไม่สามารถแสดงความคิดเห็นได้เป็นเหตุผลว่าทำไม เสียงดังกราวควรจะสามารถค้นหาความเร็ว 25% -O2 ในแอปพลิเคชันของฉันเมื่อมีการเปลี่ยนแปลงประเภทสมาร์ทพอยน์เตอร์ที่ใช้อย่างหนัก เพื่อการเปลี่ยนแปลงเดียวกัน ฉันรู้หรือไม่ว่าฉันควรจะเชียร์หรือโห่การค้นพบว่าการเพิ่มประสิทธิภาพ -2 ของ Clang นั้นมีความไวอย่างมากต่อภูมิปัญญาของตัวเลือกสมาร์ทพ้อยท์ของฉัน

อัปเดต: GCC 4.8.1 v clang 3.3

ผลลัพธ์ที่สอดคล้องกันคือ:

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.1 | 442 | 443 |1.00 |
----------|-----|-----|-----|
Clang-3.3 | 374 | 370 |1.01 |
----------|-----|-----|------
GCC/Clang |1.18 |1.20 |

ความจริงที่ว่า executables ทั้งสี่ตอนนี้ใช้เวลาเฉลี่ยมากขึ้นกว่าก่อนหน้านี้ในการประมวลผล 1 ไฟล์ไม่ได้สะท้อนประสิทธิภาพของคอมไพเลอร์ล่าสุด มันเป็นเพราะความจริงที่ว่าสาขาการพัฒนาต่อมาของแอปพลิเคชันการทดสอบได้ทำการแยกส่วนที่ซับซ้อนในระหว่างนี้และจ่ายมันในความเร็ว เฉพาะอัตราส่วนที่มีนัยสำคัญ

ประเด็นที่ควรทราบตอนนี้ไม่ใช่เรื่องใหม่ที่น่าจับตามอง:

  • GCC ไม่สนใจการเพิ่มประสิทธิภาพ -O3
  • เสียงดังกราวให้ประโยชน์อย่างมากจากการปรับให้เหมาะสม -O3
  • เสียงดังกังวานเต้น GCC ด้วยอัตรากำไรขั้นต้นที่สำคัญในทำนองเดียวกันในการเพิ่มประสิทธิภาพในแต่ละระดับ

เมื่อเปรียบเทียบกับผลลัพธ์เหล่านี้กับ GCC 4.7.2 และ clang 3.2 นั้นแสดงให้เห็นว่า GCC ได้กลับมาเป็นผู้นำของ clang ประมาณหนึ่งในสี่ในแต่ละระดับการเพิ่มประสิทธิภาพ แต่เนื่องจากแอปพลิเคชันทดสอบได้รับการพัฒนาอย่างมากในขณะเดียวกันเราไม่สามารถเชื่อคุณลักษณะนี้เพื่อติดตามการสร้างรหัสของ GCC (ครั้งนี้ฉันได้บันทึกภาพรวมแอปพลิเคชันที่ได้รับการกำหนดเวลาและสามารถใช้งานได้อีกครั้ง)

อัปเดต: GCC 4.8.2 v clang 3.4

ฉันเสร็จสิ้นการอัปเดตสำหรับ GCC 4.8.1 v Clang 3.3 โดยบอกว่าฉันจะติดกับ coan snaphot เดียวกันสำหรับการอัปเดตเพิ่มเติม แต่ฉันตัดสินใจที่จะทดสอบสแน็ปช็อตนั้น (ฉบับที่ 301) และในสแน็ปช็อตการพัฒนาล่าสุดฉันมีที่ผ่านชุดทดสอบ (ฉบับที่ 619) สิ่งนี้ให้ผลลัพธ์ของลองจิจูดเล็กน้อยและฉันมีแรงจูงใจอื่น:

การโพสต์ดั้งเดิมของฉันระบุว่าฉันไม่ได้ใช้ความพยายามในการเพิ่มประสิทธิภาพของโคนันเพื่อเพิ่มความเร็ว นี่เป็นกรณีของการหมุนรอบ 301. อย่างไรก็ตามหลังจากที่ฉันสร้างอุปกรณ์จับเวลาเข้าไปในชุดทดสอบ coan ทุกครั้งที่ฉันรันชุดทดสอบผลกระทบด้านประสิทธิภาพของการเปลี่ยนแปลงล่าสุดจะทำให้ฉันเผชิญหน้า ฉันเห็นว่ามันมักจะมีขนาดใหญ่ที่น่าแปลกใจและแนวโน้มที่เป็นเชิงลบมากขึ้นกว่าที่ฉันรู้สึกว่าจะได้รับประโยชน์จากการได้รับประโยชน์จากการทำงาน

โดย rev 308 เวลาประมวลผลเฉลี่ยต่อไฟล์อินพุตในชุดทดสอบนั้นเพิ่มขึ้นเป็นสองเท่านับตั้งแต่การโพสต์ครั้งแรกที่นี่ ณ จุดนั้นฉันกลับถึงนโยบาย 10 ปีของฉันโดยไม่รบกวนการทำงาน ในช่วงเวลาเร่งด่วนของการปรับปรุงที่มีประสิทธิภาพสูงสุดถึง 619 ครั้งเป็นเรื่องที่ต้องคำนึงถึงเสมอและมีจำนวนมากที่ต้องทำการเขียนใหม่ตัวรับน้ำหนักหลักบนบรรทัดที่เร็วกว่าเดิม มันน่าสนใจที่จะเห็นปฏิกิริยาของคอมไพเลอร์แต่ละตัวต่อการกลับรถครั้งนี้

นี่คือเมทริกซ์เวลาที่คุ้นเคยในขณะนี้สำหรับการสร้างคอมไพเลอร์สองรายการล่าสุดของ rev.301:

ผลลัพธ์ coan - rev.301

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 428 | 428 |1.00 |
----------|-----|-----|-----|
Clang-3.4 | 390 | 365 |1.07 |
----------|-----|-----|------
GCC/Clang | 1.1 | 1.17|

เรื่องราวที่นี่มีการเปลี่ยนแปลงเล็กน้อยจาก GCC-4.8.1 และ Clang-3.3 การแสดงของ GCC นั้นเป็นเรื่องเล็ก ๆ เสียงดังกราวของเรื่องเล็ก ๆ น้อย ๆ เสียงรบกวนอาจเป็นสาเหตุของเรื่องนี้ได้ เสียงดังกังวานยังคงออกมาข้างหน้า-O2และ-O3ระยะขอบที่ไม่สำคัญในการใช้งานส่วนใหญ่ แต่จะค่อนข้างน้อย

และนี่คือเมทริกซ์สำหรับการหมุนรอบ 619

coan - rev.619 ผลลัพธ์

          | -O2 | -O3 |O2/O3|
----------|-----|-----|-----|
GCC-4.8.2 | 210 | 208 |1.01 |
----------|-----|-----|-----|
Clang-3.4 | 252 | 250 |1.01 |
----------|-----|-----|------
GCC/Clang |0.83 | 0.83|

การจดบันทึกตัวเลข 301 และ 619 เคียงข้างกันหลายจุดพูดออกมา

  • ฉันตั้งเป้าหมายที่จะเขียนโค้ดที่เร็วขึ้นและคอมไพเลอร์ทั้งคู่ก็พิสูจน์ความพยายามของฉันอย่างเด่นชัด แต่:

  • GCC ตอบแทนความพยายามเหล่านั้นอย่างไม่เห็นแก่ตัวยิ่งกว่าเสียงดังกราว ที่-O2 การเพิ่มประสิทธิภาพ Clang ของ 619 build นั้นเร็วกว่าการสร้าง 301 ถึง 46%: ที่-O3Clang's ปรับปรุงคือ 31% ดี แต่ในการปรับแต่งแต่ละระดับของ GCC 619 นั้นมีค่ามากกว่าสองเท่าของ 301

  • GCC มากกว่ากลับคำว่า Clang ที่เหนือกว่าในอดีต และในแต่ละระดับการเพิ่มประสิทธิภาพ GCC เต้นเสียงดังกราว 17%

  • ความสามารถของ Clang ใน 301 build เพื่อรับประโยชน์มากกว่า GCC จาก-O3การปรับให้เหมาะสมนั้นจะหายไปใน 619 build -O3ทั้งกำไรจากคอมไพเลอร์มีความหมาย

ฉันรู้สึกประหลาดใจอย่างมากจากการพลิกกลับของโชคชะตาที่ฉันสงสัยว่าฉันอาจสร้างเสียงกราว 3.4 ที่ซบเซาอย่างไม่ตั้งใจ (ตั้งแต่ฉันสร้างมันจากแหล่งที่มา) ดังนั้นฉันจึงทำการทดสอบ 619 ครั้งด้วย Clang 3.3 ในสต็อคของ distro ผลลัพธ์ที่ได้ในทางปฏิบัติเช่นเดียวกับ 3.4

ดังนั้นเมื่อพิจารณาถึงปฏิกิริยาของการกลับรถ: ในตัวเลขที่นี่เสียงดังกังวานทำได้ดีกว่า GCC มากที่ความเร็วในการเขียนรหัส C ++ ของฉันเมื่อฉันไม่ได้ให้ความช่วยเหลือ เมื่อฉันตั้งใจช่วย GCC ทำงานได้ดีกว่าเสียงดังกราว

ฉันไม่ยกระดับการสังเกตนั้นเป็นหลักการ แต่ฉันใช้บทเรียนว่า "ผู้รวบรวมรายใดที่สร้างไบนารีที่ดีกว่า" เป็นคำถามที่แม้ว่าคุณจะระบุชุดการทดสอบที่คำตอบนั้นจะสัมพันธ์กัน แต่ก็ยังไม่ใช่ประเด็นที่ชัดเจนของการกำหนดเวลาไบนารี

เลขฐานสองที่ดีกว่าของคุณคือเลขฐานสองที่เร็วที่สุดหรือเป็นเลขที่ชดเชยได้ดีที่สุดสำหรับรหัสที่ออกแบบมาอย่างถูก? หรือดีที่สุดชดเชย รหัสที่สร้างขึ้นอย่างแพงที่ให้ความสำคัญกับการบำรุงรักษาและนำมาใช้ใหม่มากกว่าความเร็ว? ขึ้นอยู่กับลักษณะและน้ำหนักสัมพัทธ์ของแรงจูงใจของคุณในการสร้างไบนารีและข้อ จำกัด ที่คุณทำ

และในกรณีใด ๆ ถ้าคุณสนใจอย่างยิ่งในการสร้างไบนารีที่ดีที่สุดคุณควรตรวจสอบว่าการทำซ้ำของคอมไพเลอร์ต่อเนื่องส่งผลให้คุณคิดว่า "ดีที่สุด" ในการทำซ้ำโค้ดของคุณ


9
ทำไมเสียงดังกราวถึงเร็วกว่า? ตัวอย่างเช่นคอมไพเลอร์ intel ใช้ความเชี่ยวชาญของชิป intel เสียงดังกราวใช้อะไรเพื่อให้ได้เปรียบ? สามารถเขียนโค้ดใหม่เพื่อให้ gcc มีประสิทธิภาพเหมือนกันได้หรือไม่
kirill_igum

27
@krill_igum GCC และเสียงดังกราวมีความแตกต่างกัน (ซับซ้อนอย่างมาก) โปรแกรมที่เขียนโดยกลุ่มโปรแกรมเมอร์ต่าง ๆ เพื่อทำงานเดียวกัน: แปลซอร์สโค้ดเป็นรหัสวัตถุ แทบจะหลีกเลี่ยงไม่ได้ที่หนึ่งในนั้นจะทำงานนั้นดีกว่าวัดอื่นในการทดสอบที่เลือก ณ เวลาใดก็ได้ ไม่จำเป็นต้องมี "สิ่ง" พิเศษใด ๆ ที่ผู้ชนะคือ "ใช้" เพื่อ "ได้รับประโยชน์" และเนื่องจากทั้งสองโปรแกรมเป็นโอเพ่นซอร์สพวกเขาจึงไม่มีความลับจากกันและกัน
Mike Kinghan

3
มันเป็นไปได้ที่จะใช้kcachegrindเพื่อระบุฟังก์ชั่นที่ความสามารถในการปฏิบัติการที่สร้างขึ้นมีความแตกต่างกัน

4
-1: นี่เป็นนวนิยาย (หรือโพสต์บล็อก) มากกว่าคำตอบ
John Saunders

60
@ JohnSaunders: สิ่งที่คนคนหนึ่งมีรายละเอียดคำตอบในเชิงลึกสำหรับคนอื่นเป็นนวนิยายที่ไม่คู่ควรกับความสนใจของพวกเขา บอกสิ่งที่ทำให้คนสองคนนี้แยกจากกัน
เอสเอฟ

48

Phoronix ทำเกณฑ์มาตรฐานบางอย่างเกี่ยวกับเรื่องนี้ แต่มันเกี่ยวกับ Clang / LLVM เวอร์ชั่นสั้น ๆ จากไม่กี่เดือนหลัง ผลการวิจัยพบว่าสิ่งต่าง ๆ เป็นแรงผลักดันมากขึ้นหรือน้อยลง ทั้ง GCC และ Clang นั้นดีกว่าในทุกกรณี

เนื่องจากคุณต้องการใช้เสียงดังกราวล่าสุดมันอาจมีความเกี่ยวข้องน้อยกว่าเล็กน้อย จากนั้นอีกครั้ง GCC 4.6 ได้รับการกำหนดให้มีการปรับปรุงหลักสำหรับ Core 2 และ i7 อย่างเห็นได้ชัด

ฉันคิดว่าการรวบรวมความเร็วที่เร็วขึ้นของ Clang จะดีกว่าสำหรับนักพัฒนาดั้งเดิมและเมื่อคุณผลักดันโค้ดออกสู่โลก Linux distro / BSD / etc ผู้ใช้จะใช้ GCC สำหรับไบนารีที่เร็วขึ้น


2
วันนี้ฉันรันมาตรฐานการคอมไพล์ความเร็วของ Clang และมันน่าผิดหวังมากสำหรับไฟล์ C บริสุทธิ์ที่รวบรวม 35 C กับ 270 KLOC clang นั้นเร็วขึ้น 25% เมื่อฉันเห็นว่า Tinycc รวดเร็วแค่ไหนบน linux มันก็เป็นผลเสียสำหรับคอมไพเลอร์ตัวใหม่ มันจะดีขึ้นเมื่อใช้การปรับให้เหมาะสม -O2 / -O3 แต่เนื่องจากมันถูกใช้สำหรับการวางจำหน่ายการสร้างประสิทธิภาพของคอมไพเลอร์จึงไม่สำคัญในกรณีนี้
Lothar

7
@mcandre บางที Nietzche-jou ถูกคอมไพล์ด้วย Clang ในขณะที่คุณถูกคอมไพล์ด้วย GCC
Mateen Ulhaq

18

ความจริงที่ว่า Clang รวบรวมรหัสได้เร็วขึ้นอาจไม่สำคัญเท่ากับความเร็วของไบนารีที่เกิดขึ้น แต่ที่นี่เป็นชุดของมาตรฐาน


12
จริงๆแล้วมันทำ ในระหว่างการพัฒนาเวลารวบรวม (และการใช้ทรัพยากรเนื่องจากการรวบรวม) เป็นคอขวดมากกว่าประสิทธิภาพไบนารี ท้ายที่สุดเรารวบรวมในโหมด Debug ในขั้นตอนนี้ เมื่อมาถึงขั้นตอนการทดสอบและจัดส่งที่คุณเปลี่ยนเป็นโหมดการวางจำหน่ายและพยายามที่จะได้รับไบนารีที่รวดเร็วที่สุดเท่าที่จะเป็นไปได้
Matthieu M.

3
@ Matthieu M: ฉันสาบานคำตอบที่ว่า "อาจ .. " ราวกับว่าเขากำลังนำความกังวลที่อาจเกิดขึ้น ฉันคิดว่าบางทีมันก็คุ้มค่าที่จะกล่าวถึงเพราะมันรู้ว่าเกี่ยวข้องกับ OP
JM Becker

เห็นด้วยแม้ว่าทุกจุดที่ดีที่นี่ ฉันควรจะใส่ไดรฟ์ RAID 0 หรือ 2, SSD, หรือ RAM ที่เร็วกว่าและได้ประสิทธิภาพที่ดีที่สุด. exe - หากมาตรการเหล่านี้ช่วยให้คุณได้พาริตี้หรือปิด บางครั้งก็เป็นประโยชน์ในการพัฒนาด้วยคอมไพเลอร์มากกว่าหนึ่ง มันสามารถทำให้คุณรับรู้ถึงคุณสมบัติที่ไม่สามารถพกพาได้และตรวจจับข้อผิดพลาดที่ไม่สามารถตรวจจับได้หรือนำไปสู่การเสียเวลาหลายวันในการพยายามแก้ไขข้อผิดพลาดของคอมไพเลอร์

ฉันลองเปรียบเทียบวันนี้กับโค้ดจำนวนเต็มที่สำคัญที่ฉันเขียนและ GCC ทำงานได้เร็วขึ้นมาก (22S clang-llvm 25S) โดยใช้ทั้ง -O2 & -O3 คิดว่าการใช้คอมไพเลอร์สวิทช์ (gcc หรือเสียงดังกราว) ครอบคลุมคุณสมบัติที่ไม่ได้มาตรฐานมากที่สุดและคำเตือนคงที่ ในโครงการขนาดใหญ่ของคุณเองไม่ใช่การคอมไพล์รหัสของ ppl อื่น ๆ คุณกำลังทำสิ่งผิดปกติในระบบการสร้างของคุณหากเวลาคอมไพล์มีอิทธิพลเหนือเวลาลิงก์ มีเครื่องมือเช่นccache.samba.orgที่ช่วยถ้าคุณทำความสะอาดบ่อยๆ ปัญหาอีกประการหนึ่งของการเปลี่ยนแปลงคอมไพเลอร์คือการลงทุนตลอดเวลาในการทดสอบ / ตรวจสอบความถูกต้องที่ทิ้งไป
Rob11311

code.google.com/p/distccเป็นอีกโครงการหนึ่งที่สามารถเร่งความเร็วเวลาการคอมไพล์จำนวนมากหากห้องสมุดทั้งหมดต้องการคอมไพล์ใหม่เนื่องจากการเปลี่ยนแปลงโครงสร้างข้อมูลหรือเพื่อวัตถุประสงค์ในการตรวจสอบ / การตรวจสอบความถูกต้อง
Rob11311

11

มีความแตกต่างโดยรวมน้อยมากระหว่าง GCC 4.8 และ clang 3.3 ในแง่ของความเร็วของไบนารีที่ได้ ในกรณีส่วนใหญ่โค้ดที่สร้างโดยคอมไพเลอร์ทั้งสองจะทำงานคล้ายกัน ไม่มีคอมไพเลอร์สองตัวนี้ที่ควบคุมคอมไพเลอร์ตัวอื่น

เกณฑ์มาตรฐานบอกว่ามีช่องว่างประสิทธิภาพที่สำคัญระหว่าง GCC และเสียงดังกราวเป็นเรื่องบังเอิญ

ประสิทธิภาพของโปรแกรมได้รับผลกระทบจากตัวเลือกของคอมไพเลอร์ หากนักพัฒนาหรือกลุ่มนักพัฒนาใช้ GCC โดยเฉพาะโปรแกรมนั้นสามารถคาดว่าจะทำงานได้เร็วขึ้นด้วย GCC เล็กน้อยกว่า clang และในทางกลับกัน

จากมุมมองของนักพัฒนาความแตกต่างที่น่าทึ่งระหว่าง GCC 4.8+ และ clang 3.3 คือ GCC มี-Ogตัวเลือกบรรทัดคำสั่ง ตัวเลือกนี้เปิดใช้งานการปรับให้เหมาะสมที่ไม่รบกวนการดีบักตัวอย่างเช่นเป็นไปได้เสมอที่จะได้รับการติดตามสแต็กที่ถูกต้อง การไม่มีตัวเลือกนี้ในเสียงดังกราวทำให้เสียงดังกราวยากที่จะใช้เป็นคอมไพเลอร์ปรับให้เหมาะสมสำหรับนักพัฒนาบางคน


เมื่อเร็ว ๆ นี้ (3.3 และ 4.8) ฉันไม่เห็นความแตกต่างระหว่างเวลารวบรวม (ในโปรแกรม "ของฉัน" ที่มีเวลารวบรวมระหว่าง 10 วินาทีและ 30 วินาที)
alfC

9

วิธีเดียวที่จะตรวจสอบสิ่งนี้คือลองใช้งาน FWIW ฉันได้เห็นการปรับปรุงที่ดีจริง ๆ โดยใช้แอปเปิ้ล LLVM gcc 4.2 เทียบกับ gcc 4.2 ปกติ (สำหรับรหัส x86-64 ที่มี SSE ค่อนข้างมาก) แต่ YMMV สำหรับฐานรหัสที่แตกต่างกัน สมมติว่าคุณทำงานกับ x86 / x86-64 และคุณสนใจจริง ๆ ไม่กี่เปอร์เซ็นต์จากนั้นคุณควรลอง ICC ของ Intel เช่นกันเพราะนี่อาจเอาชนะ gcc ได้ - คุณสามารถรับใบอนุญาตการประเมินผล 30 วันจาก intel.com และลอง


8

ความแตกต่างที่แปลกประหลาดฉันได้บันทึกไว้ใน gcc 5.2.1 และ clang 3.6.2 คือถ้าคุณมีลูปที่สำคัญเช่น:

for (;;) {
    if (!visited) {
        ....
    }
    node++;
    if (!*node) break;
  }

จากนั้น gcc จะรวบรวม-O3หรือ-O2คลี่วงม้วนออกมาแปดครั้ง เสียงดังกราวจะไม่คลี่คลายเลย จากการทดลองและข้อผิดพลาดฉันพบว่าในกรณีเฉพาะของฉันกับข้อมูลโปรแกรมของฉันจำนวนที่เหมาะสมของการ unrolling คือห้าดังนั้น gcc overshot และ clang undershot อย่างไรก็ตามการถ่ายภาพ overshotting นั้นเป็นอันตรายต่อการแสดงดังนั้น gcc จึงทำงานได้แย่กว่ามากที่นี่

ฉันไม่มีความคิดว่าความแตกต่างที่ไม่ได้ควบคุมนั้นเป็นแนวโน้มทั่วไปหรือบางสิ่งที่เฉพาะเจาะจงกับสถานการณ์ของฉัน

ซักพักฉันเขียนนักสะสมขยะสองสามคนเพื่อสอนตัวเองเกี่ยวกับการเพิ่มประสิทธิภาพการทำงานใน C และผลลัพธ์ที่ฉันได้รับอยู่ในใจของฉันพอที่จะชอบเสียงดังกราวเล็กน้อย โดยเฉพาะอย่างยิ่งเนื่องจากการรวบรวมขยะเป็นส่วนใหญ่เกี่ยวกับตัวชี้การไล่และคัดลอกหน่วยความจำ

ผลลัพธ์คือ (ตัวเลขในไม่กี่วินาที):

+---------------------+-----+-----+
|Type                 |GCC  |Clang|
+---------------------+-----+-----+
|Copying GC           |22.46|22.55|
|Copying GC, optimized|22.01|20.22|
|Mark & Sweep         | 8.72| 8.38|
|Ref Counting/Cycles  |15.14|14.49|
|Ref Counting/Plain   | 9.94| 9.32|
+---------------------+-----+-----+

นี่คือรหัส C บริสุทธิ์ทั้งหมดและฉันไม่เรียกร้องเกี่ยวกับประสิทธิภาพของคอมไพเลอร์เมื่อรวบรวมรหัส C ++

บน Ubuntu 15.10, x86.64 และโปรเซสเซอร์ AMD Phenom (tm) II X6 1090T


4

โดยพื้นฐานแล้วคำตอบคือ: ขึ้นอยู่กับ มีเกณฑ์มาตรฐานมากมายที่มุ่งเน้นไปที่แอปพลิเคชันประเภทต่างๆ

เกณฑ์มาตรฐานของฉันในแอพของฉันคือ: gcc> icc> clang

มี IO ที่หายาก แต่มีการดำเนินการ CPU float และโครงสร้างข้อมูลจำนวนมาก

ธงคอมไพล์คือ -Wall -g -DNDEBUG -O3

https://github.com/zhangyafeikimi/ml-pack/blob/master/gbdt/profile/benchmark

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