VS 2008 C ++ build output? - PullRequest
       10

VS 2008 C ++ build output?

8 голосов
/ 04 марта 2010

Почему, когда я смотрю вывод сборки из проекта VC ++ в VS, я вижу:

1> Компиляция ...
1> a.cpp
1> b.cpp
1> c.cpp
1> d.cpp
1> e.cpp
[Т.д ...]
1> Генерация кода ...
1> x.cpp
1> y.cpp
[Т.д ...]

Вывод выглядит так, как будто несколько блоков компиляции обрабатываются до генерации кода. Это действительно происходит? Я пытаюсь сократить время сборки, и, используя предварительно скомпилированные заголовки, я получил отличные ускорения для каждого файла .cpp, но во время сообщения «Генерация кода ...» происходит относительно длительная пауза. У меня не включены ни «Оптимизация всей программы», ни «Генерация временного кода ссылки». Если это так, то почему? Почему VC ++ не компилирует каждый «.cpp» по отдельности (что включает этап генерации кода)? Если это не просто иллюзия выходных данных, возможно, здесь происходит оптимизация кросс-компиляции? Похоже, что нет никаких опций компилятора для управления этим поведением (я знаю о WPO и LTCG, как упоминалось выше).

EDIT:
Журнал сборки показывает только файлы «.obj» в выходном каталоге, по одному на строку. Нет никаких указаний на этапы «Компиляция ...» и «Генерация кода ...».

EDIT:
Я подтвердил, что это поведение не имеет ничего общего с параметром «максимальное количество параллельных сборок проектов» в Сервис -> Параметры -> Проекты и решения -> Построить и запустить . Это также не связано с параметром MSBuild build buildbobity . Действительно, если я отменю сборку до шага «Генерация кода ...», ни один из файлов «.obj» не будет существовать для самого последнего набора «скомпилированных» файлов. Это означает, что компилятор действительно обрабатывает несколько блоков перевода вместе. Почему это?

Ответы [ 5 ]

5 голосов
/ 11 марта 2010

Архитектура компилятора

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

Запуск процесса компиляции Visual Studio

В компиляторе сборки Visual Studio процесс (cl.exe) выполняется для компиляции нескольких исходных файлов с одинаковыми параметрами командной строки в одной команде. Компилятор сначала выполняет «компиляцию» последовательно для каждого файла (это, скорее всего, внешний интерфейс), но «Генерация кода» (возможно, внутренний) выполняется вместе для всех файлов после того, как с ними выполнена компиляция.

В этом можно убедиться, просмотрев файл cl.exe в Process Explorer.

Почему генерация кода для нескольких файлов одновременно

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

Оптимизация всей программы

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

Примечание: кажется, что WPO выполняется компоновщиком, поскольку он создает exe из файлов obj, но это своего рода иллюзия - файлы obj не являются реальными объектными файлами, они содержат промежуточное представление, а «компоновщик» не является реальным компоновщиком, поскольку он не только связывает существующий код, но и генерирует и оптимизирует код.

2 голосов
/ 12 марта 2010

Это не распараллеливание и не оптимизация кода.

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

Я не анализировал подробно, но мои наблюдения таковы: они происходят при переключении между модулями с разными параметрами компиляции или когда определенный объем кода проходит часть «файл за файлом». Это также этап, на котором большинство сбоев компилятора происходило в VC6.

Предположение: Я всегда предполагал, что это «сложная часть», которая улучшается за счет одновременной обработки нескольких элементов, возможно, только кода и данных, загруженных в кэш. Другая возможность состоит в том, что одноэтапная фаза пожирает память как сумасшедшую, и «Генерация кода» освобождает ее

Чтобы улучшить производительность сборки:

Купите лучшую машину, которую вы можете себе позволить
Это самое быстрое, самое дешевое улучшение, которое вы можете сделать. (если у вас уже есть один). Перейдите на Windows 7 x64, купите много оперативной памяти и i7 860 или аналогичный. (Переход с двухъядерного ядра Core2 дал мне коэффициент 6,8 при сборке на всех процессорах.)

(Не покупайте диски тоже).

Разделение на отдельные проекты для параллельных сборок
Это где 8 CPUS (даже если 4 физических + HT) с нагрузками ОЗУ приходят в игру. Вы можете включить распараллеливание для каждого проекта с опцией /MP, но это несовместимо со многими другими функциями.

1 голос
/ 11 марта 2010

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

У вас не включена оптимизация.Это остановит процесс сборки от оптимизации сгенерированного кода (или, по крайней мере, намекает на то, что оптимизации не следует делать ... Я не хотел бы гарантировать, что никакие оптимизации не выполняются).Тем не менее, процесс сборки все еще оптимизирован.Таким образом, несколько файлов .cpp собираются вместе, чтобы сделать это.

Я не уверен, как принимается решение относительно того, сколько файлов .cpp собирается вместе.Возможно, компилятор начинает обрабатывать файлы до тех пор, пока не решит, что объем памяти базы данных достаточно велик, так что если он будет увеличиваться, системе придется начинать выполнять чрезмерную передачу данных на диск и обратно на диск и повышать производительность пакетирования.Файлы cpp будут отменены.

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

0 голосов
/ 02 апреля 2010

В блоге Visual C ++ появилась новая статья, в которой подробно описаны некоторые недокументированные переключатели, которые можно использовать для определения времени / профиля различных этапов процесса сборки (я не уверен, сколько, если таковые имеются, написания применяется к версиям MSVC до VS2010). Интересный материал, который должен хотя бы немного рассказать о том, что происходит за кулисами:

Если ничего другого, это позволяет вам узнать, какие процессы, библиотеки и, по крайней мере, некоторые из фаз перевода / обработки соответствуют тем, какие сообщения вы видите в обычном выводе сборки.

0 голосов
/ 04 марта 2010

Распараллеливает сборку (или, по крайней мере, компиляцию), если у вас многоядерный процессор

edit: я почти уверен, что он распараллеливается так же, как "make -j", он компилирует несколько файлов cpp одновременно (поскольку cpp обычно независимы), но, очевидно, связывает их один раз.
На моей машине core-2 он показывает 2 задания devenv при компиляции одного проекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...