Ketika saya belajar di universitas saya sering mendengar gagasan bahwa kompiler Fortran menghasilkan kode lebih cepat daripada kompiler C untuk program yang setara.
Alasan utamanya seperti ini: kompiler Fortran memancarkan rata-rata 1,1 instruksi prosesor per baris kode, sedangkan kompiler C mengeluarkan rata-rata 1,6 instruksi prosesor per baris kode - Saya tidak ingat angka pastinya tetapi Gagasannya adalah bahwa kompiler C memancarkan lebih banyak kode mesin dan karenanya menghasilkan program yang lebih lambat.
Seberapa valid perbandingan itu? Bisakah kita mengatakan bahwa kompiler Fortran menghasilkan program yang lebih cepat daripada kompiler C atau sebaliknya dan mengapa perbedaan ini ada?
c
comparison
compiler
fortran
sharptooth
sumber
sumber
Jawaban:
IIRC salah satu alasan utama mengapa Fortran dikatakan lebih cepat adalah tidak adanya pointer aliasing , sehingga mereka dapat menggunakan optimasi yang tidak dapat digunakan oleh kompiler C:
Tapi saya setuju dengan yang lain di sini: Membandingkan jumlah rata-rata instruksi assembler yang dihasilkan untuk satu baris kode adalah omong kosong. Misalnya core x86 modern dapat menjalankan dua instruksi secara paralel jika mereka tidak mengakses register yang sama. Jadi Anda bisa (secara teori) mendapatkan peningkatan kinerja 100% untuk set instruksi yang sama hanya dengan memesan ulang mereka . Kompiler yang baik juga akan sering menghasilkan instruksi perakitan lebih banyak untuk mendapatkan kode lebih cepat (pikirkan loop membuka gulungan, inlining). Jumlah instruksi assembler mengatakan sangat sedikit tentang kinerja sepotong kode.
sumber
restrict
Kata kunci C memungkinkan pembuat fungsi menentukan bahwa pointer tidak memiliki alias. Apakah ini cukup untuk mengatasi perbedaannya, atau ada lebih dari itu?Perbandingan yang sama sekali tidak valid.
Pertama, seperti yang ditunjukkan oleh @ Péter Török, Anda harus terlebih dahulu membandingkan jumlah baris dalam program setara dari Fortran dan C agar ini menjadi perbandingan yang valid pada jumlah baris yang dihasilkan.
Kedua, lebih sedikit baris kode tidak selalu sama dengan program yang lebih cepat . Tidak semua instruksi mesin menggunakan jumlah siklus yang sama untuk dieksekusi , tetapi Anda juga memiliki masalah lain seperti akses memori , caching , dll.
Di atas itu semua, kode panjang berjalan bisa lebih cepat karena menghasilkan jumlah baris eksekusi yang lebih rendah (mis., Hitungan Baris! = Hitungan Baris yang Dieksekusi ).
sumber
Dan benar, program yang lebih lama bukan berarti program lebih lambat. Ini sangat tergantung pada apa yang mereka lakukan.
Saya bukan ahli Fortran, saya tahu sedikit. Membandingkan mereka, saya akan berpikir C ditulis dengan baik akan melakukan jauh lebih baik dalam kinerja dengan struktur data yang lebih kompleks dan fungsionalitas daripada Fortran. Seseorang (tolong) koreksi saya jika saya salah di sini, tapi saya pikir Fortran agak pada 'tingkat yang lebih rendah' daripada C. Jika demikian, saya yakin untuk beberapa masalah akan keluar lebih cepat pada Fortran.
Hal lain, pada pandangan pertama saya pikir Anda bertanya apakah kompiler lebih cepat. Saya benar-benar berpikir bahwa Fortran umumnya akan mengkompilasi lebih cepat untuk jumlah kode yang serupa, tetapi program yang dihasilkan dan cara kerjanya akan menjadi cerita yang berbeda. Hanya lebih mudah untuk diuraikan.
sumber
Saya pikir bagian dari itu adalah bahwa kompiler FORTRAN dirancang untuk melakukan beberapa jenis matematika dengan sangat cepat. Itulah sebabnya mengapa orang menggunakan FORTRAN, untuk melakukan perhitungan secepat mungkin
sumber
Pernyataan itu mungkin benar di masa lalu (sekitar akhir 70-an) ketika C masih dalam masa pertumbuhan, dan Fortran didukung oleh semua produsen besar dan sangat dioptimalkan. Fortrans awal didasarkan pada arsitektur IBM hal-hal yang sangat sederhana seperti aritmatika jika tentu akan menjadi satu pernyataan per instruksi perakitan. Ini berlaku untuk mesin lama seperti Data General dan Prime, yang memiliki lompatan 3 arah. Ini tidak berfungsi pada set instruksi modern yang tidak memiliki lompatan 3 arah.
Baris kode tidak sama dengan pernyataan kode. Versi Fortran sebelumnya hanya membolehkan satu pernyataan per baris. Versi Fortran yang lebih baru dapat mengambil banyak pernyataan per baris. C dapat memiliki beberapa pernyataan per baris. Pada kompiler produksi yang lebih cepat seperti Intel IVF (sebelumnya CVF, MS Powerstation) dan Intel C, benar-benar tidak ada perbedaan antara keduanya. Kompiler ini sangat dioptimalkan.
sumber
FORTRAN gaya lama mensyaratkan bahwa seorang programmer yang ingin membuat bagian dari array tersedia untuk fungsi yang diperlukan untuk meneruskan referensi ke seluruh array, bersama dengan satu atau lebih nilai integer yang menentukan subscript awal dan juga subscript akhir atau jumlah item . C memungkinkan untuk menyederhanakan ini dengan melewatkan pointer ke awal bagian bunga bersama dengan jumlah elemen. Dalam istilah langsung, ini akan membuat segalanya lebih cepat (melewati dua hal daripada tiga). Namun, secara tidak langsung, ini mungkin memperlambat segalanya dengan membatasi jenis pengoptimalan yang dapat dilakukan oleh kompiler.
Pertimbangkan fungsinya:
jika kompilator tahu bahwa masing-masing pointer akan mengidentifikasi awal array, itu dapat menghasilkan kode yang akan bertindak atas elemen-elemen array secara paralel, atau dalam urutan apa pun, karena untuk setiap x! = y, operasi pada dest [x ] tidak akan memengaruhi src1 [y] atau src2 [y]. Sebagai contoh, pada beberapa sistem kompiler dapat mengambil manfaat dari menghasilkan kode yang setara dengan:
Perhatikan bahwa setiap operasi yang memuat atau menghitung nilai memiliki setidaknya satu operasi lagi di antara itu dan operasi berikutnya yang menggunakan nilai itu. Beberapa prosesor dapat tumpang tindih pemrosesan operasi yang berbeda ketika kondisi tersebut terpenuhi, sehingga meningkatkan kinerja. Perhatikan, bagaimanapun, bahwa karena kompiler C tidak memiliki cara untuk mengetahui bahwa kode tidak akan melewati pointer ke sebagian- daerah tumpang tindih array umum, kompiler C tidak dapat melakukan transformasi di atas. Kompiler FORTRAN yang diberikan kode yang setara, bagaimanapun, dapat dan memang melakukan transformasi seperti itu.
Sementara seorang programmer C dapat mencoba untuk mencapai kinerja yang sebanding dengan secara eksplisit menulis kode yang membuka gulungan dan tumpang tindih operasi pass yang berdekatan, kode tersebut dapat dengan mudah menurunkan kinerja jika menggunakan begitu banyak variabel otomatis sehingga kompiler harus "menumpahkan" mereka untuk Penyimpanan. Pengoptimal kompiler FORTRAN kemungkinan akan tahu lebih banyak daripada seorang programmer tentang bentuk interleaving apa yang akan menghasilkan kinerja optimal dalam skenario tertentu, dan keputusan seperti itu sering kali lebih baik diserahkan kepada kompiler seperti itu. Sementara C99 berusaha memperbaiki situasi C agak dengan menambahkan
restrict
kualifikasi, yang hanya bisa digunakan di sini jikadest[]
adalah array yang terpisah dari keduanyasrc1[]
dansrc2[]
, atau jika programmer menambahkan versi loop yang terpisah untuk menangani kasus-kasus di mana semuadest
terlepas darisrc1
dansrc2
, di manasrc1[]
dandest
sama dansrc2
terpisah, di manasrc2[]
dandest[]
sama dansrc1
terpisah, dan di mana ketiga array sama. FORTRAN, sebaliknya, dapat menangani keempat kasus tanpa kesulitan menggunakan kode sumber yang sama dan kode mesin yang sama.sumber