Может ли const-correctness повысить производительность?

Я читал много раз, что принудительное выполнение const-correctness в вашем коде C или С++ является не только хорошей практикой в ​​отношении ремонтопригодности, но также может позволить вашему компилятору выполнять оптимизации. Тем не менее, я прочитал полную противоположность, тоже. что он вообще не влияет на производительность.

Следовательно, есть ли у вас примеры, когда корректность const может помочь вашему компилятору улучшить производительность вашей программы?

Ответ 1

Правильность

const не может повысить производительность, потому что const_cast и mutable находятся на этом языке и позволяют коду последовательно нарушать правила. Это становится еще хуже в С++ 11, где ваши данные const могут, например, быть указателем на std::atomic, что означает, что компилятор должен уважать изменения, сделанные другими потоками.

Тем не менее, для компилятора тривиально посмотреть на код, который он генерирует, и определить, действительно ли он записывается в данную переменную, и соответственно применять оптимизации.

Все сказанное, const правильность - это хорошая вещь в отношении ремонтопригодности. В противном случае клиенты вашего класса могут сломать внутренние члены этого класса. Например, рассмотрим стандартный std::string::c_str() - если он не смог вернуть значение const, вы сможете закрутить внутренний буфер строки!

Не используйте const по соображениям производительности. Используйте его для удобства обслуживания.

Ответ 2

Да, это возможно.

Большинство const предназначены исключительно для программиста и не помогают оптимизировать компилятор, потому что законно отбрасывать их, и поэтому они не говорят компилятору ничего полезного для оптимизации. Однако некоторые const не могут быть (юридически) отброшены, и они предоставляют компилятору полезную информацию для оптимизации.

В качестве примера, доступ к глобальной переменной, определенной с типом const, может быть встроен, а один без типа const не может быть встроен, поскольку он может меняться во время выполнения.

https://godbolt.org/g/UEX4NB

С++:

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

В практическом плане имейте в виду, что, хотя const может повысить производительность, в большинстве случаев это будет не так, или будет, но изменение не будет заметным. Основная полезность const не является оптимизацией.


Стив Джессоп дает еще один пример в своем комментарии к первому вопросу, который поднимает то, что стоит упомянуть. В области блока возможно, чтобы компилятор мог определить, будет ли переменная изменяться и оптимизироваться соответствующим образом, независимо от const, поскольку компилятор может видеть все виды использования переменной. Напротив, в приведенном выше примере невозможно предсказать, будет ли мутировать мутация foo1, поскольку она может быть изменена в других единицах перевода. Я полагаю, что гипотетический разумный сверхкомпилятор может анализировать всю программу и определять, действительно ли она действительна для встроенного доступа к foo1... но реальные компиляторы не могут.

Ответ 3

по моему опыту, no

Для скалярных переменных компилятор может определять, когда изменяется значение, и выполнять необходимую оптимизацию.

Для указателей массива константная корректность не гарантирует, что значения действительно постоянны при наличии потенциальных проблем с псевдонимом. Следовательно, компилятор не может использовать константный модификатор для выполнения оптимизации

если вы ищете оптимизацию, вы должны рассмотреть __restrict__ или специальные модификаторы/атрибуты функции: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html