Bagaimana bahasa yang kompilernya ditulis dalam C bisa lebih cepat daripada C?

175

Melihat halaman web Julia , Anda dapat melihat beberapa tolok ukur dari beberapa bahasa di beberapa algoritma (timing ditunjukkan di bawah). Bagaimana bahasa dengan kompiler yang awalnya ditulis dalam C, mengungguli kode C?

masukkan deskripsi gambar di sini Gambar: waktu benchmark relatif terhadap C (lebih kecil lebih baik, kinerja C = 1.0).

Program Perjuangan
sumber
382
Bagaimana mungkin sebuah mobil, yang merupakan objek buatan manusia, bergerak lebih cepat daripada manusia?
babou
19
Menurut tabel, Python lebih lambat dari C. Apakah Anda berpikir bahwa tidak mungkin untuk menulis kompiler C dengan Python yang menghasilkan kode yang sama dengan kompiler C favorit Anda? Lagi pula, bahasa apa yang tertulis di sana?
Carsten S
6
komentar babou tepat, tapi saya tidak berpikir kita perlu beberapa versi yang sama.
Raphael
14
Pikiran yang terkait. Banyak kompiler adalah hosting sendiri , yang berarti mereka ditulis dalam bahasa mereka sendiri (sering ditambah beberapa perakitan) dan dikompilasi dengan versi sebelumnya sendiri. Namun kompiler menjadi lebih baik dan lebih cepat. Pikiran bertiup .
Schwern

Jawaban:

263

Tidak ada hubungan yang diperlukan antara implementasi compiler dan output dari compiler. Anda bisa menulis kompiler dalam bahasa seperti Python atau Ruby, yang implementasi paling umum sangat lambat, dan kompiler itu dapat menghasilkan kode mesin yang sangat dioptimalkan mampu mengungguli C. Kompiler itu sendiri akan membutuhkan waktu lama untuk dijalankan, karena itukode ditulis dalam bahasa yang lambat. (Lebih tepatnya, ditulis dalam bahasa dengan implementasi lambat. Bahasa tidak benar-benar inheren cepat atau lambat, seperti yang ditunjukkan oleh Raphael dalam komentar. Saya memperluas ide ini di bawah.) Program yang dikompilasi akan secepatnya implementasi sendiri diperbolehkan — kami dapat menulis kompiler dengan Python yang menghasilkan kode mesin yang sama dengan kompiler Fortran, dan program kompilasi kami akan secepat Fortran, meskipun mereka membutuhkan waktu lama untuk dikompilasi.

Ini cerita yang berbeda jika kita berbicara tentang seorang penerjemah. Penerjemah harus dijalankan saat program yang ditafsirkan sedang berjalan, sehingga ada hubungan antara bahasa tempat penerjemah diimplementasikan dan kinerja kode yang ditafsirkan. Dibutuhkan beberapa optimasi runtime yang pintar untuk membuat bahasa yang ditafsirkan yang berjalan lebih cepat dari bahasa di mana penerjemah diimplementasikan, dan kinerja akhir dapat bergantung pada seberapa dapat diterima sepotong kode untuk optimasi semacam ini. Banyak bahasa, seperti Java dan C #, menggunakan runtimes dengan model hybrid yang menggabungkan beberapa manfaat dari interpreter dengan beberapa manfaat dari kompiler.

Sebagai contoh nyata, mari kita lihat lebih dekat pada Python. Python memiliki beberapa implementasi. Yang paling umum adalah CPython, penerjemah bytecode yang ditulis dalam C. Ada juga PyPy, yang ditulis dalam dialek khusus Python yang disebut RPython, dan yang menggunakan model kompilasi hibrida agak mirip JVM. PyPy jauh lebih cepat daripada CPython di sebagian besar tolok ukur; ia menggunakan segala macam trik luar biasa untuk mengoptimalkan kode saat runtime. Namun, bahasa Python yang dijalankan PyPy adalah bahasa Python yang persis sama dengan yang dijalankan CPython, kecuali beberapa perbedaan yang tidak memengaruhi kinerja.

Misalkan kita menulis kompiler dalam bahasa Python untuk Fortran. Kompiler kami menghasilkan kode mesin yang sama dengan GFortran. Sekarang kami menyusun program Fortran. Kita dapat menjalankan kompiler kita di atas CPython, atau kita dapat menjalankannya di PyPy, karena ditulis dalam Python dan kedua implementasi ini menjalankan bahasa Python yang sama. Apa yang akan kita temukan adalah bahwa jika kita menjalankan kompiler kita di CPython, kemudian jalankan di PyPy, lalu kompilasi sumber Fortran yang sama dengan GFortran, kita akan mendapatkan kode mesin yang sama persis tiga kali, sehingga program yang dikompilasi akan selalu berjalan di sekitar kecepatan yang sama. Namun, waktu yang diperlukan untuk menghasilkan program yang dikompilasi akan berbeda. CPython kemungkinan besar akan memakan waktu lebih lama dari PyPy, dan PyPy kemungkinan besar akan lebih lama dari GFortran, meskipun semuanya akan menampilkan kode mesin yang sama di akhir.

Dari pemindaian tabel tolok ukur situs web Julia, sepertinya tidak ada bahasa yang berjalan pada penerjemah (Python, R, Matlab / Oktaf, Javascript) memiliki tolok ukur di mana mereka mengalahkan C. Ini umumnya konsisten dengan apa yang saya harapkan untuk dilihat, walaupun saya dapat membayangkan kode yang ditulis dengan library Numpy Python yang sangat dioptimalkan (ditulis dalam C dan Fortran) mengalahkan beberapa kemungkinan implementasi C dari kode yang sama. Bahasa yang sama atau lebih baik daripada C sedang dikompilasi (Fortran, Julia ) atau menggunakan model hibrida dengan kompilasi parsial (Jawa, dan mungkin LuaJIT). PyPy juga menggunakan model hybrid, jadi sangat mungkin jika kita menjalankan kode Python yang sama pada PyPy dan bukan CPython, kita akan melihatnya mengalahkan C pada beberapa tolok ukur.

tsleyson
sumber
9
Ini jawaban yang luar biasa. Sangat jelas, dapat dimengerti, dan informatif. Terima kasih banyak telah meluangkan waktu untuk menulisnya!
Alex A.
7
Baik javascript dan java dijalankan dengan kompiler JIT, namun java memiliki satu tes yang lebih cepat daripada C. Alasan utama mengapa runtime / kompiler dapat berjalan lebih cepat adalah karena memiliki lebih banyak informasi yang tersedia. Kompiler C / C ++ dapat mengoptimalkan kode (biasanya) lebih dari seseorang menulis perakitan dengan tangan, hanya karena kompiler memiliki lebih banyak informasi yang tersedia untuk itu. Tentu saja, secara teori orang tersebut dapat menulis kode perakitan yang lebih baik, tetapi itu membutuhkan lebih banyak pengetahuan dan keterampilan daripada yang dimiliki kebanyakan orang. Bahasa JIT dapat memperluas ini lebih banyak lagi, mampu mengoptimalkan mesin yang tepat saat dijalankan
Programmdude
Apa yang dilakukan optimasi oleh kompiler adalah satu hal penting untuk dipertimbangkan. Compiler yang sangat pintar akan mengenali bahwa program ini adalah benchmark sintetis, dan hanya mengoptimalkan semua kode saja, hanya menciptakan output yang diharapkan.
ghellquist
@ ghellquist Tentu, jika benchmark cukup buatan dan kompilernya cukup pintar. Itu tidak secara langsung atau langsung terkait dengan bahasa implementasi kompiler, jadi saya tidak menyebutkannya di sini.
tsleyson
97

Bagaimana sebuah mesin yang dibangun oleh seorang pria bisa lebih kuat dari seorang pria? Ini pertanyaan yang persis sama.

Jawabannya adalah bahwa output dari kompiler tergantung pada algoritma yang diimplementasikan oleh kompiler itu, bukan pada langauge yang digunakan untuk mengimplementasikannya. Anda dapat menulis kompiler yang sangat lambat dan tidak efisien yang menghasilkan kode yang sangat efisien. Tidak ada yang spesial dari kompiler: hanya sebuah program yang mengambil beberapa input dan menghasilkan beberapa output.

David Richerby
sumber
33
Bagaimana program catur dapat mengalahkan manusia yang menulisnya?
Thorbjørn Ravn Andersen
25
Dengan membuat gerakan yang lebih baik! <rimshot>
Tony Ennis
Mengutip jawaban Penn Gilette mengapa tidak ada komputer yang bisa mengalahkan seorang pria di catur: "Apakah Anda berharap robot yang dirancang oleh GE kalah dari seorang pria dalam pertandingan tinju?"
Dave Kanter
90

Saya ingin membuat satu poin terhadap asumsi umum yang, menurut pendapat saya, salah sampai berbahaya ketika memilih alat untuk pekerjaan.

Tidak ada bahasa lambat atau cepat. ¹

Dalam perjalanan kami ke CPU benar-benar melakukan sesuatu, ada banyak langkah².

  1. Setidaknya satu programmer dengan skillset tertentu.
  2. Bahasa (formal) yang mereka program dalam ("kode sumber").
  3. Perpustakaan yang mereka gunakan.
  4. Sesuatu yang menerjemahkan kode sumber ke dalam kode mesin (kompiler, juru bahasa).
  5. Arsitektur perangkat keras secara keseluruhan, misalnya jumlah unit pemrosesan dan tata letak hirarki memori.
  6. Sistem operasi yang mengelola perangkat keras.
  7. Optimalisasi pada CPU.

Setiap item berkontribusi pada runtime aktual yang dapat Anda ukur, terkadang berat. "Bahasa" yang berbeda fokus pada hal yang berbeda³.

Sekedar memberi contoh.

  • 1 vs 2-4 : programmer C rata-rata cenderung menghasilkan kode yang jauh lebih buruk daripada programmer Java rata-rata, baik dalam hal kebenaran dan efisiensi. Itu karena programmer memiliki lebih banyak tanggung jawab dalam C.

  • 1/4 vs 7 : dalam bahasa tingkat rendah seperti C, Anda mungkin dapat mengeksploitasi fitur CPU tertentu sebagai programmer . Dalam bahasa tingkat yang lebih tinggi, hanya compiler / interpreter yang dapat melakukannya, dan hanya jika mereka mengetahui CPU target.

  • 1/4 vs 5 : apakah Anda ingin atau harus mengontrol tata letak memori untuk menggunakan arsitektur memori yang terbaik? Beberapa bahasa memberi Anda kendali atas itu, beberapa tidak.

  • 2/4 vs 3 : Python yang diinterpretasikan sendiri sangat lambat, tetapi ada ikatan populer untuk perpustakaan yang sangat dioptimalkan dan disusun secara alami untuk komputasi ilmiah. Jadi melakukan hal-hal tertentu dengan Python cepat pada akhirnya, jika sebagian besar pekerjaan dilakukan oleh perpustakaan ini.

  • 2 vs 4 : Penerjemah Ruby standar cukup lambat. JRuby, di sisi lain, bisa sangat cepat. Itu bahasa yang sama cepat menggunakan kompiler / juru bahasa lain.

  • 1/2 vs 4 : Menggunakan optimisasi kompiler, kode sederhana dapat diterjemahkan ke dalam kode mesin yang sangat efisien.

Intinya adalah, patokan yang Anda temukan tidak masuk akal, setidaknya tidak ketika direbus ke meja yang Anda sertakan. Bahkan jika semua yang Anda minati adalah waktu yang berjalan, Anda perlu menentukan seluruh rantai dari pemrogram ke CPU; menukar elemen apa pun dapat mengubah hasilnya secara dramatis.

Agar lebih jelas, ini menjawab pertanyaan karena itu menunjukkan bahwa bahasa yang dikompilasi (langkah 4) hanyalah sepotong teka-teki, dan mungkin tidak relevan sama sekali (lihat jawaban lain).


  1. Tentu saja ada fitur bahasa yang lebih mahal untuk diimplementasikan daripada yang lain. Tetapi keberadaan fitur tidak berarti Anda harus menggunakannya, dan fitur yang mahal dapat menghemat penggunaan banyak yang lebih murah dan dengan demikian membayar pada akhirnya. (Tentu memiliki kelebihan lain yang tidak terukur dalam menjalankan waktu.)
  2. Saya melewatkan level algoritmik karena tidak selalu berlaku dan sebagian besar tidak tergantung pada bahasa pemrograman yang digunakan. Ingatlah bahwa algoritma yang berbeda lebih cocok untuk perangkat keras yang berbeda, misalnya.
  3. Saya sengaja tidak masuk ke metrik kesuksesan yang berbeda di sini: menjalankan efisiensi waktu, efisiensi memori, waktu pengembang, keamanan, keselamatan, kebenaran (terbukti?), Dukungan alat, kemandirian platform, ...

    Membandingkan bahasa dengan satu metrik meskipun telah dirancang untuk tujuan yang sepenuhnya berbeda adalah kesalahan besar.

Raphael
sumber
1
@ Babou Setuju, penjelasan yang sangat bagus. Jadi apa yang akan menjadi metrik yang lebih baik, atau mungkin serangkaian metrik , yang dapat digunakan untuk membandingkan bahasa dengan kompiler / juru bahasa masing-masing? Juga, nitpick minor: Anda mengatakan "Tidak ada yang namanya bahasa lambat atau cepat" dan kemudian "Python itu sendiri sangat lambat", tapi saya berasumsi Anda maksudkan juru bahasa Python.
StrugglingProgrammer
2
@ Benalbrecht Maksud saya adalah tidak ada set metrik yang bagus. Ini adalah trade-off, selalu. Jika Anda membuat driver perangkat, Anda ingin benar di atas semua hal. Jika Anda membangun tulang punggung Twitter, Anda ingin menjadi efisien di atas segalanya. Dalam kedua kasus, Anda menggunakan alat dan merekrut orang-orang yang memungkinkan untuk itu. Jika Anda adalah startup yang mengutak-atik aplikasi Android, Anda menggunakan apa yang diketahui orang dan / atau apa yang meminimalkan waktu Anda ke pasar. Jika Anda mengajarkan algoritma, Anda menginginkan bahasa dengan sintaksis yang ringkas, jelas, dan sedikit ketel. Dan seterusnya. Prioritas berbeda, jadi kami memiliki bahasa yang berbeda.
Raphael
Lihat juga pertanyaan terkait tangensial ini .
Raphael
23

Ada satu hal yang terlupakan tentang pengoptimalan di sini.

Ada perdebatan panjang tentang fortran yang mengungguli C. Menyingkirkan debat yang salah: kode yang sama ditulis dalam C dan fortran (seperti yang diperkirakan penguji) dan kinerja diuji berdasarkan data yang sama. Masalahnya adalah, bahasa-bahasa ini berbeda, C memungkinkan pointer alias, sedangkan fortran tidak.

Jadi kodenya tidak sama, tidak ada batasan pada file yang diuji C, yang memberikan perbedaan, setelah menulis ulang file untuk memberitahu kompiler bahwa ia dapat mengoptimalkan pointer, runtime menjadi serupa.

Intinya di sini adalah, bahwa beberapa teknik optimasi lebih mudah (atau mulai legal) dalam bahasa yang baru dibuat.


X

Kedua VM dapat melakukan tes tekanan saat berjalan, sehingga dapat mengambil kode yang ditekan dan mengoptimalkannya atau bahkan menghitungnya selama runtime. Di muka disusun program C tidak mengharapkan di mana tekanan atau (sebagian besar waktu) ada versi generik dari executable untuk keluarga umum mesin.

Dalam tes ini ada juga JS, juga ada VM lebih cepat dari V8, dan juga melakukan lebih cepat daripada C dalam beberapa tes.

Saya telah memeriksanya, dan ada teknik optimisasi unik yang belum tersedia di kompiler C.

C compiler harus melakukan analisis statis seluruh kode sekaligus, berbaris di atas platform yang diberikan dan berkeliling masalah penyelarasan memori.

VM hanya mentransliterasikan bagian kode untuk perakitan yang dioptimalkan dan menjalankannya.

Tentang Julia - ketika saya memeriksanya beroperasi pada AST kode, misalnya GCC melewatkan langkah ini baru-baru ini mulai mengambil beberapa info dari sana. Ini ditambah kendala lain dan teknik VM mungkin menjelaskan sedikit.

Contoh: mari kita ambil loop sederhana, yang membutuhkan titik akhir akhir mulai dari variabel dan memuat bagian variabel ke dalam perhitungan yang diketahui saat runtime.

Kompiler C menghasilkan variabel pemuatan dari register.
Tetapi pada saat runtime variabel-variabel ini dikenal dan diperlakukan sebagai konstanta melalui eksekusi.
Jadi alih-alih memuat variabel dari register (dan tidak melakukan caching karena dapat berubah, dan dari analisis statis tidak jelas) mereka diperlakukan sepenuhnya seperti konstanta dan dilipat, diperbanyak.

Jahat
sumber
12

Jawaban sebelumnya memberikan cukup banyak penjelasan, meskipun sebagian besar dari sudut pragmatis, karena sebanyak pertanyaan masuk akal , sebagaimana dijelaskan dengan sangat baik oleh jawaban Raphael .

Menambah jawaban ini, kita harus mencatat bahwa, saat ini, kompiler C ditulis dalam C. Tentu saja, sebagaimana dicatat oleh Raphael, output dan kinerjanya mungkin tergantung, antara lain, pada CPU yang sedang berjalan. Tetapi itu juga tergantung pada jumlah optimasi yang dilakukan oleh kompiler. Jika Anda menulis dalam C kompilator pengoptimalan yang lebih baik untuk C (yang kemudian Anda kompilasi dengan yang lama untuk dapat menjalankannya), Anda mendapatkan kompiler baru yang membuat bahasa C lebih cepat daripada sebelumnya. Jadi, berapa kecepatan C? Perhatikan bahwa Anda bahkan dapat mengkompilasi kompiler baru dengan dirinya sendiri, sebagai pass kedua, sehingga kompilasi lebih efisien, meskipun masih memberikan kode objek yang sama. Dan teorema ketenagakerjaan penuh menunjukkan bahwa mereka tidak ada habisnya untuk perbaikan seperti itu (terima kasih kepada Raphael untuk penunjuknya).

Tapi saya pikir mungkin ada gunanya mencoba memformalkan masalah, karena menggambarkan dengan sangat baik beberapa konsep dasar, dan khususnya pandangan denotasional versus operasional.

Apa itu kompiler?

CSTCCSTP:SP SP:T TP

CSTCST{(P:S,P:T)PSSPTT}

CSTPSPTP

P:TP:SCST

Menyempurnakan argumen, kami mungkin ingin kompiler memiliki efisiensi yang baik, sehingga terjemahan dapat dilakukan dalam waktu yang wajar. Jadi kinerja program kompiler penting bagi pengguna, tetapi tidak berdampak pada semantik. Saya mengatakan kinerja, karena kompleksitas teoretis dari beberapa penyusun dapat jauh lebih tinggi dari yang diharapkan.

Tentang bootstrap

Ini akan menggambarkan perbedaan, dan menunjukkan aplikasi praktis.

SISCST:SSCST:SISP:SP:TST

CST:SSCST:TTTT

babou
sumber
"Yang penting secara semantik adalah apa yang dilakukan, bukan seberapa (dan seberapa cepat) itu dilakukan" - perlu disebutkan bahwa kriteria non-fungsional ada dalam praktik. Ada banyak program target yang secara fungsional setara, tetapi kami mungkin lebih memilih beberapa daripada yang lain karena beberapa alasan (efisiensi, ukuran, perataan memori yang lebih baik, ...). Artinya, pandangan kompiler sebagai fungsi yang Anda tetapkan lebih terbatas daripada yang kita inginkan (itu juga sering melompati efek samping, misalnya I / O). Ini melayani tujuan jelas yang Anda inginkan.
Raphael
@Raphael Mengenai teorema ketenagakerjaan penuh, saya memikirkan hal itu (dalam komentar saya tentang C), tetapi saya tidak tahu namanya, dan menunda menemukan referensi. Terima kasih sudah melakukannya. --- Semantik yang saya bicarakan adalah kompiler, bukan dari program target. Program target dipertahankan secara sintaksis dan operasional, bukan hanya secara semantik. Atau apakah saya salah mengerti ucapan Anda. Saya mengedit untuk membuat hal-hal yang lebih tepat dalam teks saya.
babou
@Raphael Karena Anda tidak menghapus komentar Anda, apakah itu berarti saya salah paham, atau tidak menjawabnya dengan benar? Bagaimana mungkin pandangan kompiler (bukan dari program yang dikompilasi) sebagai fungsi terlalu terbatas, dari sudut pandang semantik. Tentu saja, sebagai suatu fungsi, ia dapat mengambil argumen lain dari hanya program yang dikompilasi, seperti arahan optimasi) tetapi ini adalah detail yang tidak akan mengubah diskusi.
babou
Saya pikir komentar saya berdiri sebagai penunjuk ke arah "ada lebih dari model ini". Apa yang Anda tulis tidak salah, tapi itu bukan segalanya. Secara teoritis, ini tampak jelas: "" fungsi compiler tidak per se didefinisikan dengan baik karena ada yang tak terhingga banyak program sasaran mungkin, semua semantik setara. Yang harus dipilih adalah bagian yang sangat penting dalam mendesain kompiler.
Raphael
CP
6

Dengan teorema speedup Blum ada program yang ditulis dan dijalankan pada kombinasi komputer / kompiler yang paling cepat akan berjalan lebih lambat daripada program untuk hal yang sama pada PC pertama Anda yang menjalankan BASIC yang diartikan. Tidak ada "bahasa tercepat". Yang bisa Anda katakan adalah bahwa jika Anda menulis algoritma yang sama dalam beberapa bahasa (implementasi; seperti yang disebutkan, ada banyak kompiler C yang berbeda di sekitar, dan saya bahkan menemukan penerjemah C yang cukup mampu), itu akan berjalan lebih cepat atau lebih lambat di masing-masing .

Tidak mungkin ada hierarki "selalu lebih lambat". Ini adalah fenomena yang semua orang fasih dalam beberapa bahasa menyadari: Setiap bahasa pemrograman dirancang untuk jenis aplikasi tertentu, dan implementasi yang lebih banyak digunakan telah dioptimalkan dengan penuh kasih untuk jenis program tersebut. Saya cukup yakin bahwa misalnya program untuk bermain-main dengan string yang ditulis dalam Perl mungkin akan mengalahkan algoritma yang sama yang ditulis dalam C, sementara program yang mengunyah array besar bilangan bulat di C akan lebih cepat daripada Perl.

vonbrand
sumber
1
"Setiap bahasa pemrograman dirancang untuk jenis aplikasi tertentu" Sebenarnya, sebagian besar bahasa pemrograman yang digunakan orang sebenarnya adalah bahasa tujuan umum, kebalikan dari yang dirancang untuk aplikasi spesifik. Hanya saja bahasa-bahasa tertentu pada akhirnya lebih banyak digunakan dalam domain-domain tertentu sebagian besar karena efek sosial.
Cubic
Saya kira itu tergantung pada seberapa luas Anda menafsirkan istilah "tipe aplikasi tertentu". Meskipun benar bahwa kebanyakan bahasa utama tidak DSL, mereka pasti sedang dirancang dengan penggunaan tertentu dalam pikiran. C dirancang untuk mengimplementasikan Unix. Java dirancang untuk scripting TV Interaktif. Smalltalk dirancang untuk mengajar anak-anak. ECMAScript dirancang untuk skrip web sisi server dan sisi klien. Perl dirancang untuk pemrosesan teks dan skrip Unix. PHP dirancang untuk skrip web sisi server. Erlang dirancang untuk keandalan. Skema dirancang untuk menjelajahi ...
Jörg W Mittag
... yayasan OO dan Model Aktor. APL dirancang sebagai notasi untuk mengajar matematika. Julia dirancang untuk pemrograman ilmiah. Semua bahasa itu sekarang tentu saja digunakan di luar domain masalah asli mereka, tetapi masih ada beberapa properti dalam bahasa itu yang membuat mereka lebih baik atau lebih buruk cocok untuk jenis aplikasi tertentu, meskipun mereka semua dapat digunakan untuk membangun semua jenis sesuatu.
Jörg W Mittag
4

Mari kita kembali ke baris asli: "Bagaimana bahasa yang kompilernya ditulis dalam C bisa lebih cepat daripada C?" Saya pikir ini benar-benar dimaksudkan untuk mengatakan: bagaimana sebuah program yang ditulis dalam Julia, yang intinya ditulis dalam C, akan lebih cepat daripada sebuah program yang ditulis dalam C? Secara khusus, bagaimana mungkin program "mandel" seperti yang ditulis dalam Julia berjalan di 87% dari waktu pelaksanaan program "mandel" yang setara ditulis dalam C?

Risalah Babou adalah satu-satunya jawaban yang benar untuk pertanyaan ini sejauh ini. Semua tanggapan lain sejauh ini kurang lebih menjawab pertanyaan lain. Masalah dengan teks babou adalah bahwa deskripsi teoretis panjang-paragraf-panjang "Apa itu kompiler" ditulis dalam istilah bahwa poster asli mungkin akan mengalami kesulitan memahami. Siapa pun yang memahami konsep yang dirujuk oleh kata "semantik", "denotasional", "realisasi", "dapat dihitung", dan seterusnya akan sudah tahu jawaban atas pertanyaan itu.

Jawaban yang lebih sederhana adalah bahwa baik kode C, maupun kode Julia, tidak langsung dieksekusi oleh mesin. Keduanya harus diterjemahkan, dan proses terjemahan itu memperkenalkan banyak cara agar kode mesin yang dapat dieksekusi bisa lebih lambat atau lebih cepat, tetapi tetap menghasilkan hasil akhir yang sama. Baik C dan Julia melakukan kompilasi, yang berarti serangkaian terjemahan ke bentuk lain. Biasanya, file teks yang dapat dibaca manusia diterjemahkan ke beberapa representasi internal, dan kemudian dituliskan sebagai urutan instruksi yang dapat dipahami komputer secara langsung. Dengan beberapa bahasa, ada lebih dari itu, dan Julia adalah salah satunya - ia memiliki kompiler "JIT", yang berarti seluruh proses penerjemahan tidak harus terjadi sekaligus untuk seluruh program. Tetapi hasil akhirnya untuk bahasa apa pun adalah kode mesin yang tidak memerlukan terjemahan lebih lanjut, kode yang dapat dikirim langsung ke CPU untuk membuatnya melakukan sesuatu. Pada akhirnya, INI adalah "perhitungan", dan ada lebih dari satu cara untuk memberi tahu CPU cara mendapatkan jawaban yang Anda inginkan.

Orang bisa membayangkan bahasa pemrograman yang memiliki operator "plus" dan "multiply", dan bahasa lain yang hanya memiliki "plus". Jika perhitungan Anda membutuhkan perkalian, satu bahasa akan "lebih lambat" karena tentu saja CPU dapat melakukan keduanya secara langsung, tetapi jika Anda tidak memiliki cara untuk menyatakan perlunya mengalikan 5 * 5, Anda harus menulis "5 + 5 + 5 + 5 + 5 ". Yang terakhir akan membutuhkan lebih banyak waktu untuk sampai pada jawaban yang sama. Agaknya, ada beberapa hal yang terjadi dengan Julia; mungkin bahasanya memungkinkan programmer untuk menyatakan tujuan yang diinginkan dari komputasi Mandelbrot diatur dengan cara yang tidak mungkin untuk secara langsung diekspresikan dalam C.

Prosesor yang digunakan untuk benchmark disebutkan sebagai Xeon E7-8850 2.00GHz CPU. Tolok ukur C menggunakan kompilator gcc 4.8.2 untuk menghasilkan instruksi untuk CPU itu, sementara Julia menggunakan kerangka kerja kompiler LLVM. Mungkin saja backend gcc (bagian yang menghasilkan kode mesin untuk arsitektur CPU tertentu) tidak sebagus backend LLVM. Itu bisa membuat perbedaan dalam kinerja. Ada juga banyak hal lain yang terjadi - kompiler dapat "mengoptimalkan" dengan mungkin mengeluarkan instruksi dalam urutan yang berbeda dari yang ditentukan oleh programmer, atau bahkan tidak melakukan beberapa hal sama sekali jika dapat menganalisis kode dan menentukan mereka tidak dituntut untuk mendapatkan jawaban yang benar. Dan programmer mungkin telah menulis bagian dari program C dengan cara yang membuatnya lambat, tetapi tidak

Semua ini adalah cara untuk mengatakan: ada banyak cara untuk menulis kode mesin untuk menghitung set Mandelbrot, dan bahasa yang Anda gunakan memiliki efek besar pada bagaimana kode mesin itu ditulis. Semakin banyak Anda memahami tentang kompilasi, set instruksi, cache, dan sebagainya, semakin lengkap Anda untuk mendapatkan hasil yang Anda inginkan. Hasil utama dari hasil benchmark yang dikutip untuk Julia adalah bahwa tidak ada satu bahasa atau alat yang terbaik dalam segala hal. Faktanya faktor kecepatan terbaik di seluruh bagan adalah untuk Java!

Randall Krieg
sumber
2

Kecepatan program yang dikompilasi tergantung pada dua hal:

  1. Karakteristik kinerja mesin yang mengeksekusinya
  2. Isi file yang dapat dieksekusi

Bahasa yang ditulis oleh kompiler tidak relevan dengan (1). Sebagai contoh, kompiler Java dapat ditulis dalam C atau Java atau Python, tetapi dalam semua kasus "mesin" yang menjalankan program adalah JVM.

Bahasa yang ditulis oleh kompiler tidak relevan dengan (2). Sebagai contoh, tidak ada alasan mengapa kompiler C yang ditulis dengan Python tidak dapat menampilkan file yang dapat dieksekusi sama persis dengan kompiler C yang ditulis dalam C atau Java.

Artelius
sumber
1

Saya akan mencoba menawarkan jawaban yang lebih pendek.

Inti dari pertanyaan terletak pada definisi "kecepatan" suatu bahasa .

Kebanyakan jika tidak semua tes perbandingan kecepatan tidak menguji berapa kecepatan maksimum yang dimungkinkan. Sebagai gantinya mereka menulis sebuah program kecil dalam bahasa yang ingin mereka uji, untuk memecahkan masalah. Saat menulis program, programmer menggunakan apa yang mereka anggap * sebagai praktik terbaik dan konvensi bahasa, pada saat ujian. Kemudian mereka mengukur kecepatan program dijalankan.

* Asumsinya terkadang salah.

Peter
sumber
0

Kode yang ditulis dalam bahasa X yang Compilernya ditulis dalam C, dapat mengungguli kode yang ditulis dalam C, asalkan, kompiler C melakukan optimasi yang buruk dibandingkan dengan bahasa X. Jika kita menjaga optimasi dari diskusi maka jika kompiler X dapat menghasilkan lebih baik kode objek selain yang dihasilkan oleh kompiler C, maka juga kode yang ditulis dalam X dapat memenangkan perlombaan.

Tetapi jika bahasa X adalah bahasa yang ditafsirkan, dan penerjemah ditulis dalam C, dan jika kita mengasumsikan bahwa penerjemah bahasa X dan kode yang ditulis dalam C dikompilasi oleh kompiler C yang sama, maka sama sekali tidak ada kode yang ditulis dalam X akan mengungguli kode ditulis dalam C, asalkan kedua implementasi mengikuti algoritma yang sama dan menggunakan struktur data yang setara.

jayraj
sumber
2
Apa yang ditambahkan dari jawaban sebelumnya? Juga, saya tidak berpikir paragraf kedua Anda benar, karena alasan yang dijabarkan dalam jawaban lain.
Raphael