Dengan prediksi cabang, dan juga pengaruh optimisasi kompiler, kode mana yang cenderung menawarkan kinerja superior?
Perhatikan bahwa bRareExceptionPresent mewakili kondisi yang tidak biasa. Ini bukan jalur logika yang normal.
/* MOST COMMON path must branch around IF clause */
bool SomeFunction(bool bRareExceptionPresent)
{
// abort before function
if(bRareExceptionPresent)
{
return false;
}
.. function primary body ..
return true;
}
/* MOST COMMON path does NOT branch */
bool SomeFunction(bool bRareExceptionPresent)
{
if(!bRareExceptionPresent)
{
.. function primary body ..
}
else
{
return false;
}
return true;
}
optimization
theory
dyasta
sumber
sumber
Jawaban:
Di dunia saat ini, tidak masalah, jika tidak ada sama sekali.
Prediksi cabang dinamis (sesuatu yang dipikirkan selama beberapa dekade (lihat Analisis Skema Prediksi Cabang Dinamis Beban Kerja Sistem yang diterbitkan pada tahun 1996)) adalah tempat yang cukup umum.
Contohnya dapat ditemukan pada prosesor ARM. Dari Pusat Info Arm pada Prediksi Cabang
Pertanyaannya kemudian adalah "apa prediksi cabang dinamis di prosesor lengan?" Pembacaan berkelanjutan prediksi cabang dinamis menunjukkan bahwa ia menggunakan skema prediksi 2 bit (dijelaskan dalam makalah) membangun informasi tentang apakah cabang diambil dengan kuat atau lemah atau tidak diambil.
Seiring waktu (dan maksud saya beberapa melewati blok itu) ini membangun informasi ke mana kode akan pergi.
Untuk prediksi statis , ini terlihat pada cara kode terlihat dengan sendirinya dan ke arah mana cabang dibuat pada tes - untuk instruksi sebelumnya atau yang lebih jauh dalam kode:
Seperti disebutkan oleh Sparky, ini didasarkan pada pemahaman bahwa loop lebih sering daripada tidak, loop. Cabang-cabang loop mundur (memiliki cabang di akhir loop untuk memulai kembali di atas) - biasanya melakukan ini.
Bahaya mencoba menebak kompiler adalah Anda tidak tahu bagaimana kode itu akan dikompilasi (dan dioptimalkan). Dan sebagian besar, itu tidak masalah. Dengan prediksi dinamis, dua kali melalui fungsi ini akan memprediksi melewatkan pernyataan penjaga untuk pengembalian prematur. Jika kinerja dua pipeline memerah adalah kinerja kritis, ada hal lain yang perlu dikhawatirkan.
Waktu yang diperlukan untuk membaca satu gaya di atas yang lain kemungkinan lebih penting - membuat kode menjadi bersih sehingga manusia dapat membacanya, karena kompiler akan melakukannya dengan baik tidak peduli seberapa berantakan atau ideal Anda menulis kode.
sumber
Pemahaman saya adalah bahwa pertama kali CPU menemukan cabang, itu akan memprediksi (jika didukung) bahwa cabang maju tidak diambil dan cabang mundur adalah. Alasan untuk ini adalah bahwa loop (yang biasanya bercabang mundur) diasumsikan diambil.
Pada beberapa prosesor, Anda dapat memberikan petunjuk dalam instruksi perakitan tentang jalur mana yang lebih mungkin. Rincian ini luput dari saya saat ini.
Selain itu, beberapa kompiler C juga mendukung prediksi cabang statis sehingga Anda dapat memberi tahu kompiler cabang mana yang lebih mungkin. Pada gilirannya itu dapat mengatur ulang kode yang dihasilkan, atau menggunakan instruksi yang dimodifikasi untuk memanfaatkan informasi ini (atau bahkan mengabaikannya saja)
Semoga ini membantu.
sumber
__builtin_expect
?