Re[5]: Инициализация статической переменной
От: watchmaker  
Дата: 16.04.15 17:35
Оценка: 85 (4)
Здравствуйте, Кодт, Вы писали:

W>>Да механизмов можно много придумать. Например, можно менять точку входа в функцию после первой инициализации (скажем, при виртуальных вызовах всё равно же идёт косвенная адресация и поправить vtable можно очень дёшево чтобы последующие вызовы пропускали инициализацию).


К>Плохая идея.

Так в этом и смысл сообщения — избавляясь от проверки придётся жертвовать чем-то другим.


К>- поэтому либо компилятор декомпозирует функцию на анонимные подфункции с косвенной адресацией — по штуке на каждый такой блок, — либо получается комбинаторный взрыв.

Ложная дихотомия. Конечно всё не ограничивается этими двумя "либо". PGO и трассирующие jit — ещё пара альтернатив. Тем более, что обычно и не требуется оптимизировать таким образом код, который запускается единожды или не запускается совсем. А вот найти на этапе PGO горячий цикл и сделать для него отдельную функцию — это как раз весьма разумно.

К>комбинаторный взрыв.

Да и комбинаторный взрыв тут не имеет неотвратимого характера.
Даже сейчас gcc с опцией -O3 заменяет проверки переменных флагов на специализацию функций без динамических проверок. Собственно, как долго он так будет делать — зависит только от настроек оптимизации. Можешь сам попробовать скомпилировать код вида
bool function0();
...

void run(unsigned iterations, bool flag0, bool flag1, bool flag2, bool flag3, bool flag4, bool flag5, bool flag6) {
  for(; iterations > 0; --iterations) {
     flag0 || function0();
     flag1 || function1();
     flag2 || function2();
     flag3 || function3();
     flag4 || function4();
     flag5 || function5();
     flag6 || function6();
  }
}

Так если взять 8 флагов, то (c настройками по умолчанию) gcc спокойно сгенерирует 255 функций run, специализировав каждую под свой набор флагов (проверку которых, он исключит из цикла). Сделай 10 флагов — и gcc не создаст 1023 функций, а вернётся к динамической проверке флагов. Никакого комбинаторного взрыва — все ограничено.
Собственно, и признак инициализации static переменной не сильно отличается по смыслу от явного bool флага из примера. Так что если компилятор сочтёт нужным такую оптимизацию, то он сделать её он сможет (раз уже сейчас делает).
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.