Visual studio отключить оптимизацию кода

Обновлено: 07.07.2024

Имя опции говорит что-то, но что Visual Studio/компилятор действительно делает и каковы реальные последствия?

Изменить: если вы ищете google, вы можете найти этот адрес, но на самом деле я не ищу. Интересно, что происходит. Например, почему циклы получают меньше времени и т.д.

ОТВЕТЫ

Ответ 1

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

Переменные хранятся в регистрах

Как только вы включаете оптимизацию, компилятор применяет множество различных методов, чтобы заставить код работать быстрее, в то же время делая то же самое. Наиболее очевидное различие между оптимизированными и неоптимизированными сборками в Visual C++ заключается в том, что значения переменных хранятся в регистрах как можно дольше в оптимизированных сборках, в то время как без оптимизации они всегда сохраняются в памяти. Это влияет не только на скорость кода, но и на отладку. В результате этой оптимизации отладчик не может надежно получить значение переменной во время выполнения кода.

Другие оптимизации

Существует несколько других оптимизаций, применяемых компилятором, как описано в документах MSDN "Параметры/O (Оптимизировать код)". Для общего описания различных методов оптимизации см. Статью Wikipedia Compiler Optimization.

Ответ 2

Он удаляет все инструкции NOP, которые в противном случае мы могли бы использовать, чтобы помочь в отладке. Когда оптимизация отключена (и включена информация об отладке), компилятор будет выдавать инструкции NOP для строк, у которых нет фактического ИЛ, связанного с ними, но который вы можете захотеть включить точку останова. Наиболее распространенным примером чего-то подобного будет "End If" оператора "If" - там нет реального IL, испускаемого для End If, поэтому мы не выдаем NOP, отладчик не позволит вам установить точку останова в теме. Включение оптимизации заставляет компилятор не выделять NOP.

Мы выполняем простой базовый блок-анализ генерируемого IL для удаления блоков мертвого кода. То есть мы разрываем каждый метод на блоки IL, разделенные инструкциями ветвления. Проводя быстрый анализ того, как блоки взаимосвязаны, мы можем идентифицировать любые блоки, в которых нет ветвей. Таким образом, мы можем вычислить блоки кода, которые никогда не будут выполнены и могут быть опущены, что делает сборку немного меньшей. На данный момент мы также выполняем некоторые небольшие оптимизации ветвей - например, если вы GoTo другой оператор GoTo, мы просто оптимизируем первый GoTo для перехода к второй цели GoTo.

Мы выделяем атрибут DebuggableAttribute с параметром IsJITOptimizerDisabled, равным False. В принципе, это позволяет JIT времени выполнения оптимизировать код, как он считает нужным, включая переупорядочивание и встраивание кода. Это приведет к созданию более эффективного и меньшего кода, но это означает, что попытка отладки кода может быть очень сложной (как кто-нибудь, кто попробовал это, скажет вам). Фактический список того, что оптимизация JIT - это то, чего я не знаю, может быть, кто-то вроде Криса Брумме в какой-то момент перезвонит. Длинным и, тем не менее, является то, что оптимизационный коммутатор позволяет оптимизировать, что может сделать установку контрольных точек и более сложную работу над вашим кодом.

Ответ 3

Короткий ответ: use -Ox и пусть компилятор выполнит свою работу.

Длинный ответ: эффект разного рода оптимизаций невозможно точно предсказать. Иногда оптимизация для быстрого кода фактически дает меньший код, чем при оптимизации размера. Если вы действительно хотите получить последние 0,01% производительности (по скорости или по силе), вам нужно сравнить различные комбинации параметров.

Кроме того, в последних версиях Visual Studio есть опции для более продвинутых оптимизаций, таких как оптимизация времени соединения и оптимизация с помощью профиля.

У меня есть проект, использующий CMake, который не может скомпилировать этот код на VS 2015 из-за ошибки компилятора. (взаимодействие между разрешением шаблона, оптимизацией и обработкой исключений).

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

Как мне изменить уровень оптимизации по умолчанию для MSVC 2015 на /O0 в сборках Release и RelWithDebInfo ?

Моя наивная реализация была бы условной заменой в CMAKE_CXX_FLAGS - безопасно ли это в будущем?

3 ответа

Эта ошибка компилятора мешает компоновщику мусором, насколько я могу отследить проблему (VS2015 является новым, на момент написания этой статьи не было выпущено никаких патчей / обновлений). В компоновщике происходит сбой. Похоже, компилятор считает, что все прошло хорошо.

Когда эта ошибка «возбуждена», проблема заключается в коде, который использует сгенерированный объект шаблона. Другими словами, даже если вы отключите оптимизацию в заголовке, но снова включите оптимизацию в теле, это все равно приведет к сбою компоновщика. Что «работает», так это отключить оптимизацию кода, который создает экземпляры и использует функции-члены объекта шаблона (вы можете оставить оптимизацию для всего кода за пределами этой цели).

Например, в коде, опубликованном в вопросе, оставьте оптимизацию во всех заголовках. В функции, которая ИСПОЛЬЗУЕТ шаблон, выполните:

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

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

Таким образом, код можно использовать, не беспокоясь о конфигурациях сборки (то есть, он будет работать как для сборки CMAKE, так и для сборки IDE) без необходимости обременять последующих пользователей кода (с чем-либо, кроме определения, чтобы контролировать, выполняется ли оптимизация. отключен).

Если это возможно в вашей ситуации, вы также можете попробовать что-то вроде:

Такой вид повторного написания кода позволяет обойти ошибку и компилировать без сбоя компоновщика.

Кроме того, это тоже обходит проблему:

Кроме того, что мне любопытно и представляет собой немного лучший дизайн (поскольку он не требует, чтобы один класс возился с членами другого)

Хорошая новость в том, что ЕСТЬ решение, которое не требует изменения правил сборки проекта, оставляет включенной оптимизацию и фактически идентично.

Проще всего выполнять отладку кода, когда он НЕ оптимизирован. Когда код оптимизирован, компилятор и среда выполнения вносят изменения в выпущенный код ЦП, поэтому он выполняется быстрее, но имеет не такое прямое сопоставление с начальным исходным кодом. Если сопоставление менее прямое, отладчикам часто не удается определить значения локальных переменных и пошаговое выполнение кода и точки останова могут не работать должным образом.

Дополнительные сведения о JIT-отладке см. в этой документации.

Как правило, конфигурация сборки "Выпуск" создает оптимизированный код, а конфигурация сборки "Отладка" — нет. Свойство MSBuild Optimize определяет, нужно ли компилятору оптимизировать код.

Параметр "Отключать JIT-оптимизацию при загрузке модуля (только управляемый код)"

Чтобы найти параметр Отключать JIT-оптимизацию при загрузке модуля (только управляемый код) , щелкните Сервис > Параметры, а затем выберите страницу Общие в узле Отладка.

Отключение JIT-оптимизации

Когда следует включить параметр "Отключать JIT-оптимизацию"?

Установите этот флажок, если вы скачали библиотеки DLL из другого источника, например пакета NuGet, и хотите отладить код в этой библиотеке DLL. Чтобы отключение вступило в силу, необходимо также найти файл символов (PDB) для этой библиотеки DLL.

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

  • Оптимизированный код выполняется быстрее. Если вы отключаете оптимизацию для большей части кода, это может повлиять на производительность.
  • Если включен только пользовательский код, отладчик даже не будет пытаться загружать символы для оптимизированных DLL. Поиск символов может занять много времени.

Ограничения для использования параметра "Отключать JIT-оптимизацию"

Существует две ситуации, когда включение этого параметра НЕ работает.

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


После написания прошлой статьи, я понял, что у меня осталось еще некоторое количество информации, не относящейся к ускорению компиляции решения, но позволяющей несколько повысить производительность самой Visual Studio в процессе работы над кодом. А поскольку мы все-таки работаем над кодом изрядное количество времени, намного приятнее делать это в быстро работающей IDE. К сожалению, в этой статье не будет графиков, поскольку весьма тяжело измерить, насколько стало быстрее открываться меню или какое-то окно. Тем не менее, я надеюсь, что кто-то может найти для себя в этих советах что-то ценное и сэкономить себе немного времени.

Добавьте /nosplash к ярлыку запуска Visual Studio
Честно говоря, время запуска уменьшится не сильно, но психологически будет казаться, что Студия грузится быстрее.

Отключите кнопку F1
Это делается в «Environment->Keyboard». Вы ведь всё-равно не пользуетесь этой кнопкой, правда? А если случайно нажмёте, то, в зависимости от версии VS начнут открываться новые окна или запуститься браузер — всё это весьма долго.

Выключите анимацию
«Environment->General->Animate environment tools». Оставим анимацию фанатам красивостей. А мы ведь суровые программисты, нам ни к чему.

Отключите стартовую страницу
Она занимает время при запуске студии (в особенности, если лезет в Интернет за всякими новостями и советами). Отключается в «Environment->Startup».

Выключите «Track Active Item in Solution Explorer»
Неужели Вы правда ею пользуетесь? Если нет — выключите. Отключается в «Projects and Solutions»

Отключение разнообразных красивостей
Вот тут об этом написано детальнее. Отключается в «Environment->General->Visual experience»

Удаление лишних плагинов
Каждый плагин — это минус к производительности Студии. Если у Вас стоит что-то лишнее — удаляйте.

  • Закройте Visual Studio.
  • Удалите все .ncb файлы для Вашего решения.
  • Удалите или переименуйте файл C:\Program Files\Microsoft Visual Studio 9.0\VC\vcpackages\feacp.dll (часть «9.0» отличается для разных версий Visual Studio).

Запуск Студии и компиляция проекта перед приходом на работу
На моей рабочей машине каждое утро, за час до моего прихода на работу запускается скрипт, закрывающий Visual Studio, делающий update кода из репозитория и по-новому запускающий Студию и компиляцию решения в ней. Приходя на работу я вижу откытую IDE, в которой сразу видно текущее состояние решения (компилируется\нет) и лог процедуры update, по которой понятно что именно изменилось со вчерашнего вечера. Всё это экономит мне 10 минут ежедневно.

Правка: Если вы ищете Google, вы можете найти этот адрес , но это не совсем то, что я ищу. Интересно, что происходит на самом деле. Например, почему циклы получают меньше времени и т.д.

Без оптимизации компилятор создает очень тупой код - каждая команда компилируется очень простым способом, так что она выполняет предназначенную задачу. По умолчанию в сборках Debug оптимизации отключены, поскольку без оптимизаций созданный исполняемый файл напрямую соответствует исходному коду.

Переменные хранятся в регистрах

Как только вы включите оптимизацию, компилятор применяет множество различных методов, чтобы заставить код работать быстрее, в то же время делая то же самое. Наиболее очевидное различие между оптимизированными и неоптимизированными сборками в Visual C++ состоит в том, что значения переменных хранятся в регистрах как можно дольше в оптимизированных сборках, в то время как без оптимизации они всегда сохраняются в памяти. Это влияет не только на скорость кода, но и на отладку. В результате этой оптимизации отладчик не может надежно получить значение переменной, когда вы шагаете по коду.

Другие оптимизации

Есть несколько других оптимизаций, применяемых компилятором, как описано в / O Опции (Оптимизировать код) MSDN docs . Для общего описания различных методов оптимизации см. статья Wikipedia Compiler Optimization .

Он удаляет все инструкции NOP, которые мы в противном случае выпустили бы для отладки. Когда оптимизация выключена (и включена информация об отладке), компилятор будет выдавать инструкции NOP для строк, с которыми не связан фактический IL, но на которых вы, возможно, захотите установить точку останова. Наиболее распространенным примером чего-то подобного является "End If" оператора "If" - фактический IL не генерируется для End If, поэтому мы не испускаем NOP, отладчик не позволит вам установить точку останова в теме. Включение оптимизации заставляет компилятор не выдавать NOP.

Мы делаем простой базовый анализ блоков сгенерированного IL, чтобы удалить любые блоки мертвого кода. То есть мы разбиваем каждый метод на блоки IL, разделенные инструкциями ветвления. Сделав быстрый анализ того, как блоки взаимосвязаны, мы можем определить любые блоки, в которых нет ответвлений. Таким образом, мы можем определить блоки кода, которые никогда не будут выполнены и могут быть опущены, делая сборку немного меньше. Мы также делаем небольшую оптимизацию ветвления на этом этапе - например, если вы переходите к другой инструкции GoTo, мы просто оптимизируем первый GoTo, чтобы перейти к цели второго GoTo.

Мы генерируем атрибут DebuggableAttribute с IsJITOptimizerDisabled, установленным в False. По сути, это позволяет JIT во время выполнения оптимизировать код так, как он считает нужным, включая переупорядочение и встраивание кода. Это даст более эффективный и меньший код, но это означает, что попытка отладки кода может быть очень сложной (как скажет любой, кто попробовал ее). Фактический список того, что такое JIT-оптимизация, - это то, чего я не знаю - возможно, кто-то, как Крис Брамм, в какой-то момент вмешается в это. Суть в том, что переключатель оптимизации обеспечивает оптимизацию, которая может усложнить установку точек останова и пошаговое выполнение кода.

Короткий ответ: используйте -Ox и позвольте компилятору делать свою работу.

Длинный ответ: эффект различных видов оптимизаций невозможно предсказать точно. Иногда оптимизация для быстрого кода на самом деле дает меньший код, чем при оптимизации по размеру. Если вы действительно хотите получить последние 0,01% производительности (по скорости или по размеру), вы должны сравнить различные комбинации параметров.

Кроме того, в последних версиях Visual Studio есть опции для более продвинутых оптимизаций, таких как оптимизация во время соединения и оптимизация на основе профилей.

Читайте также: