Kann Konstanzkorrektheit die Leistung verbessern?

90

Ich habe mehrfach gelesen, dass das Erzwingen der Konstantenkorrektheit in Ihrem C- oder C ++ - Code nicht nur eine gute Praxis in Bezug auf die Wartbarkeit ist, sondern auch Ihrem Compiler ermöglicht, Optimierungen durchzuführen. Ich habe jedoch auch das genaue Gegenteil gelesen - dass es die Leistung überhaupt nicht beeinträchtigt.

Haben Sie daher Beispiele, bei denen die Konstantenkorrektheit Ihrem Compiler dabei helfen kann, die Leistung Ihres Programms zu verbessern?

Shuhalo
quelle
49
Konstanzkorrektheit ist eine der BESTEN Praktiken in Bezug auf Wartbarkeit. Wenn Ihr C ++ - Code nicht const-korrekt ist, ist es im Grunde ein Haufen Mist, der darauf wartet, dass eine Katastrophe eintritt. Es ist nicht beabsichtigt, die Leistung zu beeinträchtigen.
2
@ Neil Butterworth: Leider ist das Gegenteil nicht der Fall.
Beta
6
Hier ist ein Beispiel, bei dem constein Leistungsunterschied aufgetreten ist : stackoverflow.com/questions/1121791/… . Es handelte sich jedoch im Wesentlichen um ein Problem der Implementierungsqualität. constnicht festzustellen , ob der Compiler könnte rechtlich die Optimierung machen, es ist einfach passiert , dass Version des Compilers zu machen , schlug fehl , wenn es fehlt.
Steve Jessop
3
Ich bin mir ziemlich sicher, dass "morgennebel" im ersten Satz ein "nur" verpasst hat: Es ist viel sinnvoller mit "ist nicht nur eine gute Praxis".
IanH
2
@ IanH Ja, das habe ich mir überlegt. Das OP hatte jedoch genügend Zeit, um dies zu klären. Ich werde wirklich von Leuten abgehakt, die Fragen stellen und dann einfach verschwinden.

Antworten:

77

constKorrektheit kann die Leistung nicht verbessern, da const_castund mutablein der Sprache ist und Code die Regeln konform brechen kann. Dies wird in C ++ 11 noch schlimmer, wo Ihre constDaten beispielsweise ein Zeiger auf a sein können std::atomic, was bedeutet, dass der Compiler Änderungen berücksichtigen muss, die von anderen Threads vorgenommen wurden.

Trotzdem ist es für den Compiler trivial, den generierten Code zu überprüfen, festzustellen, ob er tatsächlich in eine bestimmte Variable schreibt, und Optimierungen entsprechend anzuwenden.

Das alles gesagt, constKorrektheit ist eine gute Sache in Bezug auf Wartbarkeit. Andernfalls könnten Clients Ihrer Klasse die internen Mitglieder dieser Klasse beschädigen. Betrachten Sie zum Beispiel den Standard std::string::c_str()- wenn er keinen konstanten Wert zurückgeben könnte, könnten Sie mit dem internen Puffer des Strings herumschrauben!

Nicht constaus Leistungsgründen verwenden. Verwenden Sie es aus Gründen der Wartbarkeit.

Billy ONeal
quelle
31
"Sie könnten mit dem internen Puffer der Zeichenfolge herumschrauben!" - Entscheidend ist, dass Sie versehentlich mit dem internen Puffer herumschrauben können. Compiler-Fehler constsind Wegweiser mit der Aufschrift "Sie machen etwas Dummes".
Steve Jessop
4
... und const-casts sind Wegweiser, die sagen: "Der Autor dieses Codes versucht, etwas Kluges zu tun" ;-)
Steve Jessop
5
@Steve Jessop - oder const-cast sind Wegweiser mit der Aufschrift "Ich versuche, einen const-korrekten Code-Haufen mit einem nicht-const-korrekten Code zu verbinden, und ich kann auch keinen reparieren". Was, lassen Sie mich Ihnen sagen, keineswegs klug ist, sondern nur nervt.
Michael Kohne
7
@ Michael - ja, fairer Punkt. Vielleicht ist der ursprüngliche Wegweiser nicht "du machst etwas Dummes", sondern "jemand macht etwas Dummes".
Steve Jessop
Godbolt und Arduino sagten mir, dass Konstanzkorrektheit nicht nur zum Spaß ist.
Grat
31

Ja, kann es.

Die meisten consts dienen ausschließlich dem Programmierer und helfen dem Compiler nicht bei der Optimierung, da es legal ist, sie wegzuwerfen, und sie dem Compiler nichts Nützliches für die Optimierung mitteilen. Einige consts können jedoch nicht (legal) weggeworfen werden, und diese liefern dem Compiler nützliche Informationen zur Optimierung.

Beispielsweise kann der Zugriff auf eine mit einem constTyp definierte globale Variable eingebunden werden, während eine ohne constTyp nicht eingefügt werden kann, da sie sich zur Laufzeit ändern kann.

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

Denken Sie in der Praxis daran, dass constdie Leistung zwar verbessert werden kann, in den meisten Fällen jedoch nicht oder nicht, aber die Änderung nicht spürbar ist. Der Hauptnutzen von constist nicht die Optimierung.


Steve Jessop gibt in seinem Kommentar zur ursprünglichen Frage ein weiteres Beispiel, das etwas Erwähnenswertes aufwirft. In einem Blockbereich kann ein Compiler ableiten, ob eine Variable mutiert wird, und entsprechend optimieren, unabhängig davon const, da der Compiler alle Verwendungen der Variablen sehen kann. Im obigen Beispiel ist es dagegen unmöglich vorherzusagen, ob foo1eine Mutation vorliegt, da sie in anderen Übersetzungseinheiten geändert werden könnte. Ich nehme an, ein hypothetischer empfindungsfähiger Ultra-Compiler könnte ein gesamtes Programm analysieren und feststellen, ob der Inline-Zugriff auf foo1... gültig ist, echte Compiler jedoch nicht.

Praxeolitisch
quelle
@ericcurtin Deshalb habe ich den Compiler in der Antwort nicht erwähnt. Normalerweise würde ich beim Posten der generierten Assembly sicherstellen, dass der Compiler und die Version angegeben werden. Dies ist jedoch eine Optimierung, die jeder wichtige Optimierungs-Compiler ausführt, sodass ich nicht den Eindruck erwecken wollte, dass dies nur für einen Compiler gilt.
Praxeolitic
1
@Acorn Hier ist das gleiche Beispiel, jedoch mit einem Klassenobjekt: godbolt.org/z/R-Zfgc . Außerdem haben die Variablen im Beispiel eine externe Verknüpfung.
Praxeolitic
6

nach meiner erfahrung nein

Für skalare Variablen kann der Compiler bestimmen, wann der Wert geändert wird, und die erforderliche Optimierung selbst durchführen.

Für Array-Zeiger ist die Konstantenkorrektheit keine Garantie dafür, dass die Werte bei potenziellen Aliasing-Problemen wirklich konstant sind. Daher kann der Compiler den const-Modifikator nicht allein verwenden, um Optimierungen durchzuführen

Wenn Sie nach einer Optimierung suchen, sollten Sie __restrict__spezielle Funktionsmodifikatoren / -attribute in Betracht ziehen : http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Anycorn
quelle