Saat ini saya menggunakan GCC, tetapi saya menemukan Dentang baru-baru ini dan saya sedang mempertimbangkan untuk beralih. Ada satu faktor penentu - kualitas (kecepatan, jejak memori, keandalan) dari biner yang dihasilkannya - jika gcc -O3
dapat menghasilkan biner yang berjalan 1% lebih cepat atau membutuhkan memori 1% lebih sedikit, itu adalah pemecah kesepakatan.
Clang menawarkan kecepatan kompilasi yang lebih baik dan jejak memori waktu kompilasi yang lebih rendah daripada GCC, tapi saya benar-benar tertarik pada tolok ukur / perbandingan dari perangkat lunak yang dikompilasi yang dihasilkan - bisakah Anda mengarahkan saya ke beberapa atau menggambarkan pengalaman Anda?
Jawaban:
Berikut adalah beberapa penemuan terbaru meskipun sempit dari tambang dengan GCC 4.7.2 dan Dentang 3.2 untuk C ++.
UPDATE: GCC 4.8.1 v clang 3.3 perbandingan ditambahkan di bawah ini.
UPDATE: GCC 4.8.2 v clang 3.4 ditambahkan untuk itu.
Saya memelihara alat OSS yang dibangun untuk Linux dengan GCC dan Dentang, dan dengan kompiler Microsoft untuk Windows. Alat, coan, adalah preprocessor dan penganalisa file sumber C / C ++ dan kodelines seperti: jurusan profil komputasional pada penguraian dan penanganan file rekursi-keturunan. Cabang pengembangan (yang terkait dengan hasil ini) terdiri saat ini sekitar 11K LOC dalam sekitar 90 file. Ini dikodekan, sekarang, dalam C + + yang kaya akan polimorfisme dan templat dan tetapi masih terperosok dalam banyak tambalan oleh masa lalunya yang tidak terlalu jauh dalam peretasan bersama C. Semantik yang dipindahkan tidak dieksploitasi secara tegas. Ini single-threaded. Saya tidak mencurahkan upaya serius untuk mengoptimalkannya, sementara "arsitektur" sebagian besar tetap ToDo.
Saya menggunakan Clang sebelum 3.2 hanya sebagai kompiler eksperimental karena, terlepas dari kecepatan kompilasi yang superior dan diagnostik, dukungan standar C ++ 11 yang tertinggal versi GCC kontemporer dalam hal yang dilakukan oleh coan. Dengan 3.2, celah ini telah ditutup.
Linux harness test saya untuk proses pengembangan coan saat ini kira-kira 70K sumber file dalam campuran kasus parser satu-file, tes stres mengkonsumsi 1000-an file dan tes skenario mengkonsumsi <1K file. Selain melaporkan hasil pengujian, harness terakumulasi dan menampilkan total file yang dikonsumsi dan run time yang dikonsumsi dalam coan (itu hanya melewati setiap baris perintah coan ke
time
perintah Linux dan menangkap dan menambahkan angka yang dilaporkan). Pengaturan waktu tersanjung oleh fakta bahwa sejumlah tes yang mengambil 0 waktu yang dapat diukur semuanya akan bertambah hingga 0, tetapi kontribusi tes tersebut dapat diabaikan. Statistik waktu ditampilkan di akhirmake check
seperti ini:Saya membandingkan kinerja uji harness antara GCC 4.7.2 dan Dentang 3.2, semua hal sama kecuali kompiler. Pada Clang 3.2, saya tidak lagi memerlukan diferensiasi preprocessor antara traktat kode yang akan dikompilasi oleh GCC dan Clang alternatif. Saya membangun perpustakaan C ++ yang sama (GCC) di setiap kasus dan menjalankan semua perbandingan secara berurutan dalam sesi terminal yang sama.
Level optimalisasi standar untuk build rilis saya adalah -O2. Saya juga berhasil menguji build di -O3. Saya menguji setiap konfigurasi 3 kali back-to-back dan rata-rata 3 hasil, dengan hasil sebagai berikut. Angka dalam sel data adalah jumlah rata-rata mikrodetik yang dikonsumsi oleh coan yang dapat dieksekusi untuk memproses masing-masing file input ~ 70K (baca, parsing dan tulis output serta diagnostik).
Setiap aplikasi tertentu sangat mungkin memiliki sifat-sifat yang bermain secara tidak adil terhadap kekuatan atau kelemahan kompiler. Benchmarking yang ketat menggunakan beragam aplikasi. Dengan mengingat hal itu, fitur penting dari data ini adalah:
Perbandingan lebih lanjut yang menarik dari kedua penyusun muncul secara tidak sengaja setelah penemuan-penemuan itu. Coan secara bebas menggunakan pointer pintar dan satu seperti itu banyak dilakukan dalam penanganan file. Tipe smart-pointer khusus ini telah diketik dalam rilis sebelumnya demi diferensiasi kompiler, menjadi
std::unique_ptr<X>
jika kompiler yang dikonfigurasi memiliki dukungan yang cukup matang untuk penggunaannya seperti itu, dan sebaliknyastd::shared_ptr<X>
. Bias untukstd::unique_ptr
menjadi bodoh, karena pointer ini sebenarnya ditransfer sekitar, tetapistd::unique_ptr
tampak seperti opsi yang lebih bugar untuk menggantistd::auto_ptr
pada titik ketika varian C ++ 11 baru bagi saya.Dalam proses pembuatan eksperimental untuk mengukur kebutuhan Clang 3.2 yang terus-menerus untuk diferensiasi ini dan yang serupa, saya secara tidak sengaja membangun
std::shared_ptr<X>
ketika saya bermaksud membangunstd::unique_ptr<X>
, dan terkejut melihat bahwa hasil yang dapat dieksekusi, dengan standar -O2 optimasi, adalah yang tercepat telah melihat, terkadang mencapai 184 msecs. per file input. Dengan satu perubahan pada kode sumber, hasil yang sesuai adalah ini;Poin-poin yang perlu diperhatikan di sini adalah:
Sebelum dan setelah perubahan tipe smart-pointer, Clang dapat membangun eksekusi yang jauh lebih cepat pada optimasi -O3, dan itu dapat membangun eksekusi yang sama cepatnya pada -O2 dan -O3 ketika pointer-type itu yang terbaik -
std::shared_ptr<X>
- untuk pekerjaan.Sebuah pertanyaan yang jelas bahwa saya tidak kompeten untuk mengomentari adalah mengapa Dentang harus dapat menemukan 25% -O2 percepatan dalam aplikasi saya ketika tipe smart-pointer yang banyak digunakan berubah dari unik ke berbagi, sedangkan GCC acuh tak acuh untuk perubahan yang sama. Saya juga tidak tahu apakah saya harus menghibur atau mencemooh penemuan bahwa optimasi-O2 Clang memiliki sensitivitas yang sangat besar terhadap kebijaksanaan pilihan smart-pointer saya.
PEMBARUAN: GCC 4.8.1 v dentang 3.3
Hasil yang sesuai sekarang adalah:
Fakta bahwa keempat executable sekarang mengambil waktu rata-rata yang jauh lebih besar daripada sebelumnya untuk memproses 1 file tidak mencerminkan kinerja kompiler terbaru. Hal ini disebabkan oleh fakta bahwa cabang pengembangan selanjutnya dari aplikasi pengujian telah mengambil banyak kecanggihan parsing sementara itu dan membayarnya dengan cepat. Hanya rasio yang signifikan.
Poin-poin penting sekarang bukan novel baru:
Membandingkan hasil ini dengan yang untuk GCC 4.7.2 dan clang 3.2, menonjol bahwa GCC telah mencabut kembali sekitar seperempat dari lead clang di setiap tingkat optimasi. Tetapi karena aplikasi pengujian telah banyak dikembangkan untuk sementara waktu, seseorang tidak dapat dengan yakin menghubungkan ini dengan ketertinggalan dalam pembuatan kode GCC. (Kali ini, saya telah mencatat snapshot aplikasi dari mana timing diperoleh dan dapat menggunakannya lagi.)
PEMBARUAN: GCC 4.8.2 v dentang 3.4
Saya menyelesaikan pembaruan untuk GCC 4.8.1 v Dentang 3.3 mengatakan bahwa saya akan tetap menggunakan coan snaphot yang sama untuk pembaruan lebih lanjut. Tetapi saya memutuskan untuk menguji snapshot itu (rev. 301) dan snapshot pengembangan terbaru yang saya miliki melewati test suite-nya (rev. 619). Ini memberikan hasil sedikit bujur, dan saya punya motif lain:
Posting asli saya mencatat bahwa saya tidak mencurahkan upaya untuk mengoptimalkan kecepatan untuk coan. Ini masih terjadi pada rev. 301. Namun, setelah saya membuat aparatus timing ke dalam harness test coan, setiap kali saya menjalankan test suite dampak kinerja dari perubahan terbaru menatap wajah saya. Saya melihat bahwa itu seringkali luar biasa besar dan trennya lebih negatif daripada yang saya rasakan layaknya keuntungan dalam fungsionalitas.
Oleh rev. 308 waktu pemrosesan rata-rata per file input dalam test suite telah lebih dari dua kali lipat sejak posting pertama di sini. Pada saat itu saya mengubah kebijakan 10 tahun saya yang tidak mengganggu kinerja. Dalam serangkaian revisi intensif hingga 619, kinerja selalu menjadi pertimbangan dan sebagian besar dari mereka murni untuk menulis ulang pembawa beban utama pada saluran yang secara fundamental lebih cepat (walaupun tanpa menggunakan fitur kompiler non-standar untuk melakukannya). Akan menarik untuk melihat reaksi masing-masing kompiler terhadap putaran U ini,
Ini adalah matriks timing yang sekarang sudah umum untuk versi build dua kompiler terbaru dari rev.301:
coan - rev.301 hasil
Kisah di sini hanya sedikit berubah dari GCC-4.8.1 dan Clang-3.3. Pertunjukan GCC sedikit lebih baik. Dentang sedikit lebih buruk. Kebisingan bisa menjelaskan ini. Dentang masih keluar di depan
-O2
dan-O3
margin yang tidak penting di sebagian besar aplikasi tetapi akan penting bagi beberapa.Dan di sini adalah matriks untuk rev. 619.
coan - rev.619 hasil
Mengambil angka 301 dan 619 berdampingan, beberapa poin berbicara.
Saya bertujuan untuk menulis kode lebih cepat, dan kedua kompiler dengan tegas membenarkan upaya saya. Tapi:
GCC membayar upaya itu jauh lebih murah daripada Dentang. Pada
-O2
optimasi, Clang 619 build adalah 46% lebih cepat daripada build 301: pada-O3
peningkatan Clang adalah 31%. Bagus, tetapi pada setiap level optimisasi GCC 619 build lebih dari dua kali lebih cepat dari 301.GCC lebih dari membalikkan keunggulan mantan Clang. Dan pada setiap level optimasi, GCC sekarang mengalahkan Dentang sebesar 17%.
Kemampuan dentang di 301 membangun untuk mendapatkan lebih banyak leverage daripada GCC dari
-O3
optimasi hilang di build 619. Tidak ada kompiler yang memperoleh manfaat dari-O3
.Saya cukup terkejut dengan pembalikan nasib ini yang saya kira saya mungkin secara tidak sengaja membuat bangunan lamban dari dentang 3.4 itu sendiri (karena saya membangunnya dari sumber). Jadi saya menjalankan kembali tes 619 dengan stok distro saya, Dentang 3.3. Hasilnya praktis sama dengan untuk 3.4.
Jadi mengenai reaksi terhadap putar-U: Pada angka-angka di sini, Clang telah melakukan jauh lebih baik daripada GCC pada kecepatan perasutan dari kode C ++ saya ketika saya tidak memberikan bantuan. Ketika saya berusaha membantu, GCC melakukan pekerjaan yang jauh lebih baik daripada Dentang.
Saya tidak mengangkat pengamatan itu menjadi sebuah prinsip, tetapi saya mengambil pelajaran bahwa "Kompiler mana yang menghasilkan biner yang lebih baik?" adalah pertanyaan yang, bahkan jika Anda menentukan suite tes yang jawabannya relatif, masih bukan masalah yang jelas hanya menentukan waktu binari.
Apakah biner Anda yang lebih baik biner tercepat, atau apakah itu yang terbaik mengkompensasi kode yang dibuat murah? Atau kompensasi terbaik untuk kode yang dibuat mahal yang memprioritaskan perawatan dan penggunaan kembali melebihi kecepatan? Tergantung pada sifat dan bobot relatif dari motif Anda untuk menghasilkan biner, dan kendala yang Anda gunakan.
Dan dalam hal apa pun, jika Anda sangat peduli dalam membangun biner "yang terbaik" maka Anda sebaiknya terus memeriksa bagaimana iterasi beruntun dari kompiler mewujudkan ide Anda tentang "yang terbaik" daripada iterasi berurutan dari kode Anda.
sumber
kcachegrind
untuk menunjukkan fungsi-fungsi di mana kinerja executable berbeda dalam kinerja.Phoronix melakukan beberapa tolok ukur tentang ini, tetapi ini tentang versi snapshot dari Dentang / LLVM dari beberapa bulan yang lalu. Hasilnya adalah hal-hal yang lebih atau kurang dorongan; baik GCC maupun Dentang secara definitif lebih baik dalam semua kasus.
Karena Anda akan menggunakan dentang terbaru, itu mungkin sedikit kurang relevan. Kemudian lagi, GCC 4.6 dijadwalkan untuk memiliki beberapa optimasi utama untuk Core 2 dan i7, rupanya.
Saya pikir kecepatan kompilasi Clang yang lebih cepat akan lebih baik untuk pengembang asli, dan kemudian ketika Anda mendorong kode keluar ke dunia, distro Linux / BSD / dll. pengguna akhir akan menggunakan GCC untuk binari yang lebih cepat.
sumber
Fakta bahwa Clang mengkompilasi kode lebih cepat mungkin tidak sepenting kecepatan biner yang dihasilkan. Namun, berikut adalah serangkaian tolok ukur .
sumber
Ada sangat sedikit perbedaan keseluruhan antara GCC 4.8 dan dentang 3.3 dalam hal kecepatan biner yang dihasilkan. Dalam kebanyakan kasus, kode yang dihasilkan oleh kedua kompiler berkinerja sama. Tak satu pun dari kedua kompiler ini mendominasi yang lain.
Benchmark mengatakan bahwa ada perbedaan kinerja yang signifikan antara GCC dan dentang adalah kebetulan.
Kinerja program dipengaruhi oleh pilihan kompiler. Jika pengembang atau sekelompok pengembang secara eksklusif menggunakan GCC maka program dapat diharapkan berjalan sedikit lebih cepat dengan GCC daripada dengan dentang, dan sebaliknya.
Dari sudut pandang pengembang, perbedaan penting antara GCC 4.8+ dan dentang 3.3 adalah bahwa GCC memiliki
-Og
opsi baris perintah. Opsi ini memungkinkan optimasi yang tidak mengganggu debugging, jadi misalnya selalu memungkinkan untuk mendapatkan jejak stack yang akurat. Tidak adanya opsi ini dalam dentang membuat dentang lebih sulit untuk digunakan sebagai kompilator pengoptimal untuk beberapa pengembang.sumber
Satu-satunya cara untuk menentukan ini adalah dengan mencobanya. FWIW Saya telah melihat beberapa peningkatan yang sangat baik menggunakan Apple LLVM gcc 4.2 dibandingkan dengan 4.2 gcc biasa (untuk kode x86-64 dengan SSE yang cukup banyak), tetapi YMMV untuk basis kode yang berbeda. Dengan asumsi Anda bekerja dengan x86 / x86-64 dan Anda benar-benar peduli dengan beberapa persen terakhir maka Anda harus mencoba Intel ICC juga, karena ini sering mengalahkan gcc - Anda bisa mendapatkan lisensi evaluasi 30 hari dari intel.com dan coba itu.
sumber
Perbedaan aneh yang saya catat pada gcc 5.2.1 dan clang 3.6.2 adalah bahwa jika Anda memiliki loop kritis seperti:
Maka gcc akan, ketika mengkompilasi dengan
-O3
atau-O2
, membuka gulungan secara spekulatif delapan kali. Dentang tidak akan membuka gulungannya sama sekali. Melalui trial and error saya menemukan bahwa dalam kasus khusus saya dengan data program saya, jumlah yang tepat membuka gulungan adalah lima sehingga gcc melampaui dan bergantung undershot. Namun, overshotting lebih merusak kinerja sehingga gcc tampil jauh lebih buruk di sini.Saya tidak tahu apakah perbedaan membuka gulungan adalah tren umum atau hanya sesuatu yang khusus untuk skenario saya.
Beberapa waktu yang lalu saya menulis beberapa pengumpul sampah untuk belajar lebih banyak tentang pengoptimalan kinerja dalam C. Dan hasil yang saya dapatkan ada dalam pikiran saya untuk sedikit menyukai dentang. Terutama karena pengumpulan sampah sebagian besar tentang pengejaran pointer dan menyalin memori.
Hasilnya adalah (angka dalam detik):
Ini semua kode C murni dan saya tidak membuat klaim tentang kinerja kompiler ketika mengkompilasi kode C ++.
Di Ubuntu 15.10, x86.64, dan prosesor AMD Phenom (tm) II X6 1090T.
sumber
Pada dasarnya, jawabannya adalah: itu tergantung. Ada banyak tolok ukur yang berfokus pada berbagai jenis aplikasi.
Patokan saya pada aplikasi saya adalah: gcc> icc> dentang.
Ada IO yang langka, tetapi banyak operasi CPU float dan struktur data.
kompilasi flag adalah -Wall -g -DNDEBUG -O3.
https://github.com/zhangyafeikimi/ml-pack/blob/master/gbdt/profile/benchmark
sumber