Dapatkah ketepatan const meningkatkan kinerja?

92

Saya telah membaca berkali-kali bahwa menegakkan const-correctness dalam kode C atau C ++ Anda tidak hanya praktik yang baik terkait dengan rawatan, tetapi juga memungkinkan compiler Anda untuk melakukan pengoptimalan. Namun, saya telah membaca kebalikannya - bahwa itu tidak mempengaruhi kinerja sama sekali.

Oleh karena itu, apakah Anda memiliki contoh di mana kebenaran const dapat membantu kompiler Anda dengan meningkatkan kinerja program Anda?

shuhalo
sumber
50
Const-correctness adalah salah satu praktik TERBAIK dalam hal pemeliharaan. Jika kode C ++ Anda tidak benar, itu pada dasarnya adalah tumpukan sampah, menunggu bencana menyerang. Ini tidak dimaksudkan untuk mempengaruhi kinerja.
2
@ Neil Butterworth: sayangnya kebalikannya tidak benar.
Beta
6
Berikut adalah contoh yang constmembuat perbedaan kinerja: stackoverflow.com/questions/1121791/… . Ini pada dasarnya adalah masalah kualitas implementasi. consttidak menentukan apakah kompilator dapat secara legal melakukan pengoptimalan, hanya terjadi versi kompilator gagal membuatnya ketika hilang.
Steve Jessop
3
Saya cukup yakin "morgennebel" melewatkan 'hanya' dalam kalimat pertama: Ini lebih masuk akal dengan "bukan hanya praktik yang baik".
IanH
2
@IanH Ya, saya mempertimbangkan itu. Tapi OP punya cukup waktu untuk mengklarifikasi. Saya benar-benar dikritik oleh orang-orang yang memposting pertanyaan dan kemudian menghilang begitu saja.

Jawaban:

77

constketepatan tidak dapat meningkatkan kinerja karena const_castdan mutabledalam bahasa, dan memungkinkan kode untuk secara patuh melanggar aturan. Hal ini menjadi lebih buruk di C ++ 11, di mana constdata Anda, misalnya, berupa pointer ke a std::atomic, yang berarti compiler harus menghormati perubahan yang dibuat oleh thread lain.

Meskipun demikian, sangat mudah bagi compiler untuk melihat kode yang dihasilkannya dan menentukan apakah ia benar-benar menulis ke variabel tertentu, dan menerapkan pengoptimalan yang sesuai.

Itu semua mengatakan, constkebenaran adalah hal yang baik sehubungan dengan pemeliharaan. Jika tidak, klien kelas Anda dapat merusak anggota internal kelas tersebut. Misalnya, pertimbangkan standar std::string::c_str()- jika tidak dapat mengembalikan nilai const, Anda akan dapat mengacaukan dengan buffer internal string!

Jangan gunakan constuntuk alasan kinerja. Gunakan untuk alasan pemeliharaan.

Billy ONeal
sumber
31
"Anda akan bisa mengacaukan dengan penyangga internal string!" - Yang terpenting, Anda akan dapat secara tidak sengaja mengacaukan buffer internal. Kesalahan kompiler karena constpapan penunjuk arah, mengatakan, "Anda melakukan sesuatu yang bodoh".
Steve Jessop
4
... dan pemeran polisi adalah penunjuk arah yang mengatakan, "pembuat kode ini mencoba melakukan sesuatu yang pintar" ;-)
Steve Jessop
5
@Steve Jessop - atau const-cast adalah penunjuk arah yang mengatakan "Saya mencoba memasang sekumpulan kode yang benar-benar ke yang tidak benar, dan saya tidak dapat memperbaiki salah satunya". Yang, izinkan saya memberi tahu Anda, sama sekali tidak pintar, hanya menyebalkan.
Michael Kohne
7
@ Michael - ya, poin yang adil. Mungkin tanda aslinya bukanlah "Anda melakukan sesuatu yang bodoh", melainkan "seseorang melakukan sesuatu yang bodoh".
Steve Jessop
Godbolt dan Arduino mengatakan kepada saya bahwa ketepatan const tidak hanya untuk bersenang-senang.
Selamat
31

Ya bisa.

Kebanyakan consts adalah murni untuk kepentingan programmer dan tidak membantu pengoptimalan kompiler karena legal untuk membuangnya dan mereka tidak memberitahu kompiler apapun yang berguna untuk pengoptimalan. Akan tetapi, beberapa consttidak dapat (secara legal) dibuang dan ini menyediakan informasi yang berguna bagi kompilator untuk pengoptimalan.

Sebagai contoh, akses ke variabel global yang ditentukan dengan consttipe dapat disisipkan sementara yang tanpa consttipe tidak dapat disebariskan karena mungkin berubah pada waktu proses.

https://godbolt.org/g/UEX4NB

C ++:

int foo1 = 1;
const int foo2 = 2;

int get_foo1() {
    return foo1;
}

int get_foo2() {
    return foo2;
}

asm:

foo1:
        .long   1
foo2:
        .long   2
get_foo1():
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address
        pop     rbp
        ret
get_foo2():
        push    rbp
        mov     rbp, rsp
        mov     eax, 2 ; foo2 has been replaced with an immediate 2
        pop     rbp
        ret

Dalam istilah praktis, perlu diingat bahwa meskipun constdapat meningkatkan kinerja, dalam banyak kasus tidak akan atau akan tetapi perubahan tidak akan terlihat. Kegunaan utama constbukanlah pengoptimalan.


Steve Jessop memberikan contoh lain dalam komentarnya tentang pertanyaan asli yang memunculkan sesuatu yang layak untuk disebutkan. Dalam lingkup blok, mungkin saja kompilator menyimpulkan apakah sebuah variabel akan dimutasi dan dioptimalkan sesuai, terlepas dari const, karena kompilator dapat melihat semua penggunaan variabel. Sebaliknya, pada contoh di atas, tidak mungkin untuk memprediksi apakah foo1akan dimutasi karena dapat dimodifikasi di unit terjemahan lain. Saya kira seorang ultra-compiler hipotetis dapat menganalisis seluruh program dan menentukan apakah itu valid untuk akses inline ke foo1... tetapi kompiler nyata tidak bisa.

Praxeolitik
sumber
@ericcurtin Itulah mengapa saya tidak menyebutkan compiler di jawaban. Biasanya, ketika memposting rakitan yang dihasilkan, saya akan memastikan untuk menyatakan kompiler dan versinya, tetapi ini adalah pengoptimalan yang akan dilakukan oleh setiap kompiler pengoptimalan utama sehingga saya tidak ingin memberikan kesan bahwa ini khusus untuk satu kompilator.
Praxeolitic
1
@Acorn Berikut adalah contoh yang sama tetapi dengan objek kelas: godbolt.org/z/R-Zfgc . Selain itu, variabel dalam contoh memiliki keterkaitan eksternal.
Praxeolitic
6

menurut pengalaman saya, tidak

Untuk variabel skalar, kompilator dapat menentukan kapan pun nilainya berubah dan melakukan pengoptimalan sendiri yang diperlukan.

Untuk pointer array, ketepatan const tidak menjamin bahwa nilai benar-benar konstan di hadapan masalah aliasing potensial. Oleh karena itu compiler tidak dapat menggunakan pengubah const sendirian untuk melakukan pengoptimalan

jika Anda mencari pengoptimalan, Anda harus mempertimbangkan __restrict__atau pengubah / atribut fungsi khusus: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Anycorn
sumber