MSVC10 / MP строит не многоядерные файлы в разных папках проекта - PullRequest
3 голосов
/ 12 августа 2011

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

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

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

Структура проекта на диске:

Folder\
  project.vcxproj  
  source\  
    foo.cpp  
    foo1.cpp  
  other_folder\  
    bar.cpp
    bar1.cpp
    bar3.cpp

Исходное дерево процессов:

MSBuild.exe
  cl.exe  ( passed: source\foo.cpp source\foo1.cpp )
    cl.exe  ( passed: source\foo.cpp )
    cl.exe  ( passed: source\foo1.cpp )

После завершения двух дочерних экземпляров cl.exe родительский процесс закрывается и появляется следующее дерево процессов:

MSBuild.exe
  cl.exe  ( passed: other_folder\bar.cpp other_folder\bar1.cpp other_folder\bar2.cpp )
    cl.exe  ( passed: other_folder\bar.cpp )
    cl.exe  ( passed: other_folder\bar1.cpp )
    cl.exe  ( passed: other_folder\bar2.cpp )

Наш источник хорошо организован во многих уровнях вложенных папок, которые соответствуют расположению заголовков на диске - я бы не хотел отказываться от этого, чтобы воспользоваться преимуществами /MP.

Ответы [ 4 ]

3 голосов
/ 16 августа 2011

Использование% (RelativeDir) в проекте «Имя файла объекта» (в XML-файле vcxproj, / Fo в командной строке CL.exe) заставляет msbuild пакетировать файлы cpp в cl.exe для каждого каталога. Это может оказать значительное влияние на выгоды, полученные от использования /MP.

Обратите внимание, что если ваш проект использует% (RelativeDir) для объектных файлов, вполне вероятно, что конфигурация пытается избежать столкновения .obj файлов, которые из файлов cpp с одинаковыми именами в разных папках.

Параметр командной строки / Fo обычно представляет собой папку, в которую компилятор сбрасывает файлы obj - передается только ОДИН, поэтому все файлы cpp для данного каталога могут передаваться только в CL.exe одновременно.

Это была боль - но я рад, что есть причина и решение. Надеюсь, это поможет.


Обновление

Товарищ по команде обнаружил, что каждый раз, когда параметр MSBuild отправляется в CL.exe, он, кажется, ломается или строго ограничивает / MP. Скорее всего, это связано с тем, что для правильной работы / MP на CL.exe верхнего уровня должен быть пакет файлов cpp.

Наше решение состояло в том, чтобы не использовать какие-либо параметры msbuild (я думаю, что это% params%) для «Имя файла объекта». Это потребовало, чтобы мы переименовали некоторые файлы cpp, чтобы они не конфликтовали.

Надеюсь, что это изменилось в VS2012 или VS2013.

1 голос
/ 18 июня 2015

Я обратился к этой проблеме здесь с новым подходом для избежания конфликтов .obj

https://stackoverflow.com/a/26935613/4253427

Имея в виду вышеизложенное, я могу в любое время уточнить «параметр MSBuild»отправляется в CL.exe, кажется, он ломается или строго ограничивает / MP "./ MP работает по одному вызову CL.exe за раз.Когда вы «отправляете параметр msbuild», на самом деле вы создаете несколько вызовов CL.exe с командной строкой, адаптированной к каждому исходному файлу.Они не могут быть упакованы.Вышеупомянутое связанное решение пытается обойти это путем адаптации командной строки к минимальному набору выходных каталогов.

Это должно решить вашу проблему, предотвратив клоузберы при сохранении высокой степени пакетирования, пока ваш проект не 'Не может содержать 100 файлов с именами x.cpp в разных каталогах ... обычно, по моему опыту, в гораздо большем проекте только несколько сталкивающихся .obj.

1 голос
/ 12 августа 2011

Согласно MSDN , файлы должны быть скомпилированы, когда есть поток для их обработки, но в то же время не дает никаких гарантий относительно порядка, в котором файлы должныбыть скомпилированным:

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

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

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

Это значение является меньшим из числа исходных файлов, которые вы указываете в командной строке

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

Возможно, вам удастся обойти это, если вы сгенерировали собственный файл make, в котором вы сможете одновременно обрабатывать более одной папки (или попробовать использовать инструмент MSBUILD.exe).

0 голосов
/ 01 мая 2019

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

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

Теперь большая разница в моем новом проекте заключалась в том, чтобы лучше использовать пространства имен с соответствующей структурой каталогов, что означало, что некоторые классы имели одинаковые имена и вызывали конфликты из-за того, что разные файлы .obj были в одном и том же каталоге , что приводит к изменению имени файла объекта в C / C ++ -> Output Files.

Обновления в окне вывода также соответствуют структуре каталогов. Если есть пространство имен / каталог с одним исходным файлом внутри, тогда VS показывает только один файл, который компилируется за раз. В следующем каталоге 10 исходных файлов, а VS показывает, что все 10 компилируются одновременно.

Не так много решений. Либо избегайте классов с одинаковым именем и не изменяйте имя файла объекта, либо используйте обходной путь, опубликованный zeromus , он прекрасно работает. Мое время перестройки изменилось с 03:15 до 01:20, что довольно существенно и соответствует загрузке ЦП, которая в течение большей части компиляции увеличивается с ~ 35% до 100%.

VS 2015, 2017 и 2019 все ведут себя таким образом, так что надежд на изменение не так много.

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