Параметры компилятора Visual Studio С++: Почему /O 2 определяет/Gs?

Опция компилятора Visual Studio С++ /O2 (максимальная скорость) эквивалентна

/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy

Почему /Gs? Как это помогает максимизировать скорость? (Обратите внимание, что это /Gs, а не /GS. )

Ответы

Ответ 1

/O2 не устанавливает /Gs, это ошибка в документации.

Некоторые эксперименты (легко увидеть вызовы __chkstk в сгенерированной сборке) показывает, что:

/Gs (без номера) эквивалентно /Gs 0 и означает, что всегда вставляются вызовы __chkstk. И действительно, MSDN говорит то же самое:

Если параметр /Gs задан без аргумента размера, это то же самое, что и указание /Gs 0,

/O2 не устанавливает /Gs (aka/Gs0), существует явная разница между "/O2" и "/O2/Gs". Хотя это возможно, он изменяет значение по умолчанию на нечто иное, чем на странице, похоже, что это всего лишь ошибка с документацией.

Счётчики стека никогда не подходят для производительности, он должен выполнять свою работу только тогда, когда стек переходит на новую отметку о высокой воде и в остальное время тратится впустую. Это означает, что если у вас есть цикл, который вызывает функцию 100 раз, то функция стека может увеличивать стек в первый раз, но в других 99 случаях это ничего не меняет, потому что стек уже вырос в первый раз - если понадобится для взросления вообще.

Ответ 2

/Gs вставляет стековые пробники в функции, которые используют более одной страницы (обычно 4kB) локальных переменных. Ядро стека сигнализирует ОС, что вы будете использовать много пространства стека. Если этот зонд попадает на страницу защиты, ОС знает, что ему нужно будет выделить дополнительную страницу ОЗУ для роста стека.

Это оптимизация, потому что без зонда фактический доступ к памяти вызовет распределение ОЗУ, и функция остановится до выделения ОЗУ. Зонд, как часть пролога функции, не вызывает срыв (по крайней мере, не столь серьезный).

[править] Другим преимуществом является то, что передняя панель стека будет выделять память один раз. Если вам нужно 16 КБ пространства стека и полагаться на распределение по требованию, у вас будет 4 ошибки страницы, каждая из которых вырастет стек на 4 КБ. Один зонд может заменить эти 4 ошибки одним системным вызовом.