นี่คือบางส่วนที่ทันสมัยแม้ว่าจะมีการค้นพบที่แคบของ 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|
แอปพลิเคชันใด ๆ โดยเฉพาะมีแนวโน้มที่จะมีลักษณะที่เล่นอย่างไม่ยุติธรรมต่อจุดแข็งหรือจุดอ่อนของคอมไพเลอร์ การเปรียบเทียบที่เข้มงวดมีการใช้งานที่หลากหลาย เมื่อคำนึงถึงคุณสมบัติของข้อมูลเหล่านี้แล้ว:
- การเพิ่มประสิทธิภาพ -O3 เป็นอันตรายต่อ GCC
- -O3 optimization นั้นสำคัญต่อ Clang
- ที่ -O2 optimization GCC นั้นเร็วกว่า Clang เพียงแค่มัสสุ
- ที่ -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 |
จุดที่ควรทราบคือ:
- คอมไพเลอร์ไม่ได้ประโยชน์จากการปรับให้เหมาะสม -O3
- เสียงดังกังวานเต้น GCC เช่นเดียวกับที่สำคัญในการเพิ่มประสิทธิภาพในแต่ละระดับ
- ประสิทธิภาพของ GCC นั้นได้รับผลกระทบเพียงเล็กน้อยจากการเปลี่ยนแปลงประเภทตัวชี้อัจฉริยะ
- ประสิทธิภาพของ 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%: ที่-O3
Clang'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 ทำงานได้ดีกว่าเสียงดังกราว
ฉันไม่ยกระดับการสังเกตนั้นเป็นหลักการ แต่ฉันใช้บทเรียนว่า "ผู้รวบรวมรายใดที่สร้างไบนารีที่ดีกว่า" เป็นคำถามที่แม้ว่าคุณจะระบุชุดการทดสอบที่คำตอบนั้นจะสัมพันธ์กัน แต่ก็ยังไม่ใช่ประเด็นที่ชัดเจนของการกำหนดเวลาไบนารี
เลขฐานสองที่ดีกว่าของคุณคือเลขฐานสองที่เร็วที่สุดหรือเป็นเลขที่ชดเชยได้ดีที่สุดสำหรับรหัสที่ออกแบบมาอย่างถูก? หรือดีที่สุดชดเชย
รหัสที่สร้างขึ้นอย่างแพงที่ให้ความสำคัญกับการบำรุงรักษาและนำมาใช้ใหม่มากกว่าความเร็ว? ขึ้นอยู่กับลักษณะและน้ำหนักสัมพัทธ์ของแรงจูงใจของคุณในการสร้างไบนารีและข้อ จำกัด ที่คุณทำ
และในกรณีใด ๆ ถ้าคุณสนใจอย่างยิ่งในการสร้างไบนารีที่ดีที่สุดคุณควรตรวจสอบว่าการทำซ้ำของคอมไพเลอร์ต่อเนื่องส่งผลให้คุณคิดว่า "ดีที่สุด" ในการทำซ้ำโค้ดของคุณ