Saya tahu bahwa inline adalah petunjuk atau permintaan untuk mengkompilasi dan digunakan untuk menghindari overhead panggilan fungsi.
Jadi atas dasar apa seseorang dapat menentukan apakah suatu fungsi adalah kandidat untuk inlining atau tidak? Dalam hal mana seseorang harus menghindari inlining?
inline
adalah untuk pendatang baru C ++ apaCFLAGS
yang menjadi pendatang baru Gentoo: tidak, kompilasi dengan-O3 -funroll-loops -finline-functions
tidak akan membuat Pentium lama Anda terbang;)Jawaban:
Menghindari biaya panggilan fungsi hanya setengah dari cerita.
melakukan:
inline
sebagai ganti#define
inline
: kode yang lebih cepat dan executable yang lebih kecil (lebih banyak peluang untuk tetap dalam cache kode)jangan:
saat mengembangkan perpustakaan, untuk membuat kelas dapat dikembangkan di masa mendatang Anda harus:
Ingatlah bahwa
inline
kata kunci adalah petunjuk bagi kompiler: kompiler dapat memutuskan untuk tidak menyelaraskan suatu fungsi dan dapat memutuskan untuk menyelaraskan fungsi yang tidak ditandaiinline
sejak awal. Saya biasanya menghindari fungsi menandaiinline
(selain mungkin ketika menulis fungsi yang sangat kecil).Tentang kinerja, pendekatan bijak adalah (seperti biasa) untuk membuat profil aplikasi, kemudian pada akhirnya
inline
seperangkat fungsi yang mewakili hambatan.Referensi:
EDIT: Bjarne Stroustrup, Bahasa Pemrograman C ++:
EDIT2: ISO-IEC 14882-1998, 7.1.2 Penentu fungsi
sumber
inline
jauh lebih dari sekedar petunjuk bagi kompiler. Ini mengubah aturan bahasa tentang banyak definisi. Juga, memiliki data statis bukanlah alasan untuk menghindari sebaris fungsi. Implementasi wajib mengalokasikan objek statis tunggal untuk setiap fungsi statis terlepas dari apakah fungsi tersebut dinyatakaninline
atau tidak. Kelas masih dapat diperluas jika mereka memiliki konstruktor inline dan destruktor virtual. Dan kosong brace destructor adalah satu fungsi virtual yang kadang - kadang ide yang baik untuk meninggalkan inline.inline
, hasilnya adalah bahwa fungsi tersebut tidak mendapatkan inline: Anda membayar harga untuk panggilan tersebut dan juga setiap unit terjemahan yang menyertakan dan memanggil fungsi tersebut mendapatkan salinan kode dan variabel statisnya sendiri. Alasan untuk tidak menggarisbawahi konstruktor dan destruktor ketika mengembangkan perpustakaan adalah kompatibilitas biner dengan versi perpustakaan Anda di masa depaninline
fungsi dapat digarisbawahi jika kompiler merasa menyukainya. Daninline
fungsi tidak akan diuraikan jika kompiler memutuskan untuk tidak menyertainya. Seperti kata Charles Bailey, itu mengubah aturan bahasa. Daripada menganggapnya sebagai petunjuk optimisasi, lebih tepat untuk menganggapnya sebagai konsep yang sama sekali berbeda. Katainline
kunci memberi tahu kompiler untuk memungkinkan beberapa definisi, dan tidak ada yang lain. Optimasi "inlining" dapat diterapkan ke hampir semua fungsi, apakah itu ditandai atau tidakinline
.inline
untuk mendapatkan fungsi inlining. Terkadang kita menginginkan manfaat lain, seperti berkeliling ODR.inline
tidak ada hubungannya dengan optimasi.inline
adalah instruksi kepada kompiler untuk tidak menghasilkan kesalahan jika fungsi yang diberikan definisi muncul beberapa kali dalam program dan janji bahwa definisi akan muncul di setiap terjemahan yang digunakan dan di mana pun itu muncul akan memiliki definisi yang persis sama.Mengingat aturan di atas,
inline
cocok untuk fungsi pendek yang badannya tidak mengharuskan termasuk dependensi tambahan atas apa yang hanya dibutuhkan deklarasi. Setiap kali definisi ditemukan itu harus diuraikan dan kode untuk tubuhnya dapat dihasilkan sehingga menyiratkan beberapa overhead kompiler atas fungsi yang didefinisikan hanya sekali dalam satu file sumber tunggal.Kompiler dapat inline (yaitu mengganti panggilan ke fungsi dengan kode yang melakukan tindakan fungsi itu) panggilan fungsi apa pun yang dipilihnya. Dulu kasus itu "jelas" tidak bisa inline fungsi yang tidak dideklarasikan dalam unit terjemahan yang sama dengan panggilan tetapi dengan meningkatnya penggunaan optimasi waktu tautan bahkan ini tidak benar sekarang. Yang sama benarnya adalah fakta bahwa fungsi yang ditandai
inline
mungkin tidak diuraikan.sumber
inline
kata kunci? Dan apa itu kebetulan yang menyenangkan?Memberitahu kompiler untuk menjalankan fungsi adalah optimisasi, dan aturan terpenting optimisasi adalah optimasi prematur adalah akar dari semua kejahatan. Selalu tulis kode yang jelas (menggunakan algoritma yang efisien), lalu buat profil program Anda dan hanya optimalkan fungsi yang terlalu lama.
Jika Anda menemukan fungsi tertentu sangat pendek dan sederhana, dan dipanggil puluhan ribu kali dalam putaran dalam yang ketat, itu mungkin kandidat yang baik.
Namun, Anda mungkin akan terkejut - banyak kompiler C ++ akan secara otomatis menyatukan fungsi-fungsi kecil untuk Anda - dan mereka mungkin mengabaikan permintaan Anda untuk inline juga.
sumber
/FAcs
dalam Visual Studio,-s
dalam GCC) untuk melihat apa yang dilakukannya. Dalam pengalaman saya, kedua kompiler itu menimbang kata kunci sebaris cukup banyak.inline
kata kunci sama sekali. Artinya, jika Anda melihat fungsi yang digarisbawahi, dan menghapusinline
specifier dari itu, itu akan tetap mendapatkan inline. Jika Anda memiliki contoh spesifik sebaliknya, silakan bagikan!inline
kata kunci menghalangi "menghapus kode"? Kata kunci dalam "optimasi prematur" adalah prematur , bukan optimasi. Mengatakan bahwa Anda harus aktif * menghindari optimisasi hanyalah sampah. Inti dari kutipan itu adalah Anda harus menghindari optimisasi yang mungkin tidak diperlukan, dan memiliki efek samping yang berbahaya pada kode (seperti membuatnya kurang dapat dipertahankan). Saya gagal melihat bagaimanainline
kata kunci akan membuat kode kurang bisa dipelihara, atau bagaimana bisa berbahaya untuk menambahkannya ke suatu fungsi.Cara terbaik untuk mengetahuinya adalah dengan membuat profil program Anda dan menandai fungsi-fungsi kecil yang dipanggil berkali-kali dan membakar melalui siklus CPU yang
inline
. Kata kunci di sini adalah "kecil" - setelah overhead panggilan fungsi diabaikan dibandingkan dengan waktu yang dihabiskan dalam fungsi, tidak ada gunanya untuk menyejajarkannya.Penggunaan lain yang saya sarankan adalah jika Anda memiliki fungsi-fungsi kecil yang cukup sering dipanggil dalam kode kinerja kritis untuk membuat cache miss relevan, Anda mungkin harus menyejajarkannya juga. Sekali lagi, itu adalah sesuatu yang harus bisa disampaikan oleh profiler.
sumber
Optimalisasi prematur adalah akar dari semua kejahatan!
Sebagai aturan praktis saya biasanya hanya sebaris "getter" dan "setters". Setelah kode berfungsi dan stabil, pembuatan profil dapat menunjukkan fungsi mana yang bisa mendapat manfaat dari inlining.
Di sisi lain, sebagian besar kompiler modern memiliki algoritma optimisasi yang cukup baik, dan akan menguraikan apa yang seharusnya Anda sebariskan untuk Anda.
Reasuming - menulis fungsi one-liner sebaris, dan khawatir tentang orang lain nanti.
sumber
Fungsi sebaris mungkin meningkatkan kinerja kode Anda dengan menghilangkan kebutuhan untuk mendorong argumen ke dalam tumpukan. jika fungsi yang dimaksud adalah bagian penting dari kode Anda, Anda harus membuat keputusan inline bukan inline di bagian optimisasi proyek Anda,
Anda dapat membaca lebih lanjut tentang inline di c ++ faq
sumber
Saya sering menggunakan fungsi sebaris bukan sebagai optimasi tetapi untuk membuat kode lebih mudah dibaca. Terkadang kode itu sendiri lebih pendek dan lebih mudah dipahami daripada komentar, nama deskriptif dll. Misalnya:
Pembaca segera mengetahui semantik kode yang lengkap.
sumber
Saya biasanya mengikuti aturan praktis di mana saya membuat fungsi dengan 3-4 pernyataan sederhana sebagai inline. Tetapi baik untuk diingat bahwa itu hanyalah petunjuk bagi kompiler. Panggilan terakhir untuk membuatnya sejajar atau tidak hanya diambil oleh kompiler. Jika ada lebih dari banyak pernyataan ini saya tidak akan mendeklarasikan sebaris dengan kompiler bodoh itu dapat menyebabkan kode mengasapi.
sumber
Cara terbaik adalah dengan memeriksa dan membandingkan instruksi yang dihasilkan untuk inline dan tidak inline. Namun, selalu aman untuk dihilangkan
inline
. Menggunakaninline
dapat menyebabkan masalah yang tidak Anda inginkan.sumber
Ketika memutuskan apakah akan menggunakan inline, saya biasanya mengingat ide berikut: Pada komputer modern, latensi memori dapat menjadi penghambat yang lebih besar daripada perhitungan mentah. Fungsi inlining yang disebut sering diketahui menumbuhkan ukuran yang dapat dieksekusi. Lebih jauh, fungsi seperti itu dapat disimpan dalam cache kode CPU yang akan mengurangi jumlah cache yang hilang ketika kode itu perlu diakses.
Oleh karena itu, Anda harus memutuskan sendiri: Apakah menambahkan atau mengurangi ukuran kode mesin yang dihasilkan? Seberapa besar kemungkinan bahwa memanggil fungsi akan menyebabkan cache hilang? Jika dibumbui di seluruh kode, maka saya akan mengatakan kemungkinannya tinggi. Jika dibatasi untuk satu loop ketat maka kemungkinan mudah-mudahan rendah.
Saya biasanya menggunakan inlining dalam daftar kasus saya di bawah ini. Namun, di mana Anda benar-benar peduli dengan kinerja, membuat profil sangat penting. Selanjutnya, Anda mungkin ingin memeriksa apakah kompiler benar-benar menerima petunjuk.
sumber
Juga, metode inline memiliki efek samping yang parah ketika mempertahankan proyek besar. Ketika kode inline diubah, semua file yang menggunakannya akan dibangun kembali secara otomatis oleh kompiler (itu adalah kompiler yang baik). Ini bisa menghabiskan banyak waktu pengembangan Anda.
Ketika suatu
inline
metode ditransfer ke file sumber dan tidak diuraikan lagi, seluruh proyek harus dibangun kembali (setidaknya ini adalah pengalaman saya). Dan juga ketika metode dikonversi menjadi inline.sumber
inline
atau tidak tidak masalah (selain tanpainline
kata kunci, Anda akan mendapatkan error linker - tetapiinline
kata kunci bukanlah masalah yang menyebabkan membangun kembali berlebihan.Seseorang harus menggunakan kualifikasi fungsi sebaris hanya ketika kode fungsi kecil. Jika fungsinya lebih besar Anda harus memilih fungsi normal karena menghemat ruang memori sebanding dengan pengorbanan yang relatif kecil dalam kecepatan eksekusi.
sumber
Ketika Anda berpikir kode Anda cukup kecil untuk digunakan sebagai inline dan ingatlah fungsi inline menduplikat kode Anda dan menempelkannya ketika fungsi dipanggil sehingga mungkin cukup baik untuk meningkatkan waktu eksekusi Anda tetapi juga meningkatkan konsumsi memori. Anda tidak dapat menggunakan fungsi inline ketika Anda menggunakan fungsi loop / variabel statis / rekursif / switch / goto / Virtual. Virtual berarti menunggu hingga runtime dan inline berarti selama kompilasi sehingga mereka tidak dapat digunakan secara bersamaan.
sumber
Saya telah membaca beberapa jawaban dan melihat ada beberapa hal yang hilang.
Aturan yang saya gunakan adalah tidak menggunakan inline, kecuali saya ingin inline. Tampak konyol, sekarang penjelasan.
Kompiler cukup pintar dan fungsi pendek selalu sejajar. Dan tidak pernah menjadikan fungsi panjang sebagai inline, kecuali jika programmer mengatakan untuk melakukan itu.
Sebenarnya
inline
ini adalah pesanan untuk kompiler, ia tidak punya pilihan dan setelahinline
kata kunci membuat semua kode sebaris. Jadi Anda tidak pernah bisa menggunakaninline
kata kunci dan kompiler akan mendesain kode terpendek.Jadi kapan harus digunakan
inline
?Untuk digunakan jika Anda ingin memiliki beberapa kode sebaris. Saya hanya tahu satu contoh, karena saya menggunakannya hanya dalam satu situasi. Ini adalah otentikasi pengguna.
Misalnya saya punya fungsi ini:
Tidak peduli seberapa besar fungsi ini saya ingin memilikinya sebagai inline karena itu membuat perangkat lunak saya lebih sulit untuk di-crack.
sumber