Microsoft MVP성태의 닷넷 이야기
VS.NET IDE: 49. Orcas - VC++ 다중 소스 동시 컴파일 옵션: /MP [링크 복사], [링크+제목 복사],
조회: 27997
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)

Orcas - VC++ 다중 소스 동시 컴파일 옵션: /MP


컴파일 옵션만큼은... VC++이 .NET보다는 앞서 있습니다.
일례로, 다중 코어(또는 하이퍼쓰레딩)에 따른 다중 프로젝트 동시 컴파일은 VS.NET 2005에서 VC++이 지원을 해주던 것을, .NET 프로젝트는 Orcas에 와서야 해주게 되었지요.

그런데, Orcas에서의 VC++는 한 걸음 더 나아가고 있습니다. 이젠 프로젝트 수준이 아닌, "소스 파일" 수준에서 동시 컴파일을 지원합니다. 이에 대해서는 다음에서 설명해 주고 있습니다.

차세대 Visual C++의 내부 살펴보기 - 사용자 계정 컨트롤을 위한 준비
; http://msdn.microsoft.com/msdnmag/issues/07/06/Cpp/default.aspx?loc=ko#S8

오... 멋집니다. ^^
아직은 베타 버전이라서 그런지 VC++ 프로젝트 속성창에서는 "/MP" 스위치에 대한 명시적인 옵션이 제공되지 않고 다음과 같이 직접 지정을 해야 사용이 가능합니다.

cl_new_mp_option_1.png




기대에 부풀어서, 이제 빌드 명령을 내려 보았습니다. 역시나... 딱 한방에 되진 않는군요. 어쩌겠습니까??? 하나씩 해결해 나가는 수밖에. ^^

1. /Gm (Enable Minimal Rebuild)
우선, 첫 번째... "/Gm" 옵션이 문제였습니다. 해당 컴파일러 스위치가 같이 사용되는 경우 다음과 같은 경고가 발생합니다.

cl : Command line warning D9030 : '/Gm' is incompatible with multiprocessing; ignoring /MP switch

왠지 아깝지만... 해당 프로젝트의 속성창에서 "C/C++" / "Code Generation" 범주의 "Enable Minimal Rebuild" 옵션을 해제했습니다.

2. /Yc (Create Precompiled Header File)
/Yc 옵션이 붙은 경우에도 다음과 같은 경고가 발생합니다.

cl : Command line warning D9030 : '/Yc' is incompatible with multiprocessing; ignoring /MP switch

이 옵션은 ...? 별도로 설정한 것이 없어서 난감하더군요. 아직 베타 버전이라 그런지 /Yc 옵션에 대한 판단에 버그가 있는 것 같습니다. 어느 경우에는 새로 빌드하면 위와 같은 경고가 발생하다가도, 어느 순간 이후부터는 경고가 사라졌습니다.

분명한 것은, /Yc 옵션이 stdafx.cpp 파일 이외에 지정이 되었다면 조정이 되어야 한다는 것.

3. #import 사용
보통, 외부 COM 개체를 사용하는 경우, 다음과 같은 식의 #import 구문을 이용해서 참조를 하게 되지요.

#import ".\ExternalCom.dll"

그런데, 이 옵션으로 인해 다음과 같은 오류가 발생하게 됩니다.

d:\...\test.h(265) : error C2813: #import is not supported with /MP

음... 이건 좀 불편하게 되었군요. 그런데, 가만 보니 모든 #import 구문에서 오류가 나는 것은 아니었습니다. 오호... stdafx.h 파일에서 정의된 #import에서는 오류가 안나고, 그 이외의 파일들에서는 오류가 나는군요. /MP 스위치를 이용해서 빌드를 해보면 알게 되지만, "precompiled-header" 파일을 생성해 내는 stdafx.cpp 파일인 경우에는 다른 C/C++ 파일들과 동시에 빌드되지 않는다는 점을 발견하게 됩니다. 따라서, #import 구문이 stdafx.h 파일에 있는 경우에는 다중 소스 컴파일 기능에 영향을 미치지 않기 때문에 오류가 안 나는 것이었습니다.

이 때문에, 각 소스 파일에 흩어져 있던 #import를 이용한 COM 개체 소스 생성 구문을 stdafx.h 파일로 모았습니다.




일단,,, 제가 만든 프로젝트들에서는 위와 같은 정도의 충돌만 있었을 뿐이었습니다. 모두 수정하고 나니 정상적으로 다중 소스 컴파일이 지원되었습니다. 우와~~~ ^^.

자... 이제 결과를 보기 위해. 최대한 환경을 동일하게 하기 위해서 - 디스크 캐쉬라든가 - 우선, "Clean Solution" 메뉴를 이용해서 모든 파일을 제거한 다음에 빌드를 새로 했습니다. 그다음에 다시 "Rebuild Solution" 메뉴를 이용해서 빌드를 할 때 시간을 재보았습니다.

각각 Debug 모드로 빌드했고 - 현실적으로 개발시에 가장 빈번히 빌드되는 유형이므로 - 한 번은 /MP 스위치를 주고, 한 번은 주지 않는 식으로 테스트해서 7개의 프로젝트를 가진 솔루션을 대상으로 테스트했습니다.

/MP 스위치 있을 때: 1분 42초
/MP 스위치 없을 때: 2분 11초

흠... 29초라... 기대했던 만큼은 많이 차이가 나지 않는 군요. 사실, 생각해 보면 그다지 차이가 나지 않을 법한 이유를 알게 됩니다.

왜냐하면, 이미 VS.NET 2005부터 "다중 프로젝트 동시 컴파일"을 지원하고 있었지요. 그래서, "프로젝트 의존성"이 없는 한은 (2개의 CPU 코어가 있는 경우를 가정하면,) 2개의 프로젝트를 동시에 빌드하고 있었습니다. 즉, "/MP" 스위치가 빛을 발하는 시점은, "프로젝트 의존성"으로 인해 빌드가 "직렬"로 단일 프로젝트만 대상이 되어 빌드 수행 시에 C/C++ 파일을 2개씩 동시 컴파일을 하게 되는 경우입니다.

그래서, 빌드와 함께 CPU 모니터링을 하면 재미있는 현상을 볼 수 있습니다. /MP 스위치가 있는 경우에는 거의 항상 CPU가 100%를 치고 있는 반면, /MP 스위치가 없는 경우에는 다중 프로젝트 빌드 시에는 100%를 치고 있다가도 의존성으로 인한 단일 프로젝트 빌드로 진입하게 되면 50%로 떨어지게 됩니다.

좀 더 확실한 결과를 얻기 위해서 단일 프로젝트를 대상으로만 한정지어서 빌드를 다시 해본 결과는 다음과 같았습니다.

/MP 스위치 있을 때: 46초
/MP 스위치 없을 때: 59초

음... ^^; 일단 13초에 만족합시다.




정리해 볼까요?

어찌 보면, /MP 스위치를 모든 프로젝트에 사용할 필요는 없어 보입니다. 왜냐하면 "다중 프로젝트 동시 빌드"가 이뤄지는 시점에는 /MP 스위치가 필요 없기 때문입니다. 따라서, 자신의 VC++ 솔루션을 빌드하면서 의존성으로 인한 단일 프로젝트 빌드만을 찾아내서 /MP 스위치를 적용하는 것도 현명할 수 있습니다.

하지만, 언제나 솔루션 단위의 빌드를 하는 것은 아니죠. 대개의 경우 하나의 프로젝트만을 대상으로 하면서 그 프로젝트 하나만을 다시 빌드하는 경우도 많기 때문에. 그것을 생각해 보면 모든 프로젝트에 /MP 스위치를 적용시키는 것도 좋을 것 같습니다.

크게 만족스러운 성능 차이는 아니지만. 그래도 VC++ 컴파일러의 이러한 꾸준한 노력이 마음에 듭니다. ^^



[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/17/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 46  47  48  49  50  51  52  [53]  54  55  56  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12614정성태4/24/202118389개발 환경 구성: 570. C# - Azure AD 인증을 지원하는 ASP.NET Core/5+ 웹 애플리케이션 예제 구성 [4]파일 다운로드1
12613정성태4/23/202116718.NET Framework: 1048. C# - ETW 이벤트의 Keywords에 속한 EventId 구하는 방법 (2) 관리 코드파일 다운로드1
12612정성태4/23/202116586.NET Framework: 1047. C# - ETW 이벤트의 Keywords에 속한 EventId 구하는 방법 (1) PInvoke파일 다운로드1
12611정성태4/22/202115461오류 유형: 711. 닷넷 EXE 실행 오류 - Mixed mode assembly is build against version 'v2.0.50727' of the runtime
12610정성태4/22/202115381.NET Framework: 1046. C# - 컴파일 시점에 참조할 수 없는 타입을 포함한 이벤트 핸들러를 Reflection을 이용해 구독하는 방법파일 다운로드1
12609정성태4/22/202117892.NET Framework: 1045. C# - 런타임 시점에 이벤트 핸들러를 만들어 Reflection을 이용해 구독하는 방법파일 다운로드1
12608정성태4/21/202118444.NET Framework: 1044. C# - Generic Host를 이용해 .NET 5로 리눅스 daemon 프로그램 만드는 방법 [9]파일 다운로드1
12607정성태4/21/202115662.NET Framework: 1043. C# - 실행 시점에 동적으로 Delegate 타입을 만드는 방법파일 다운로드1
12606정성태4/21/202121560.NET Framework: 1042. C# - enum 값을 int로 암시적(implicit) 형변환하는 방법? [2]파일 다운로드1
12605정성태4/18/202116899.NET Framework: 1041. C# - AssemblyID, ModuleID를 관리 코드에서 구하는 방법파일 다운로드1
12604정성태4/18/202114791VS.NET IDE: 163. 비주얼 스튜디오 속성 창의 "Build(빌드)" / "Configuration(구성)"에서의 "활성" 의미
12603정성태4/16/202116460VS.NET IDE: 162. 비주얼 스튜디오 - 상속받은 컨트롤이 디자인 창에서 지원되지 않는 문제
12602정성태4/16/202117521VS.NET IDE: 161. x64 DLL 프로젝트의 컨트롤이 Visual Studio의 Designer에서 보이지 않는 문제 [1]
12601정성태4/15/202116548.NET Framework: 1040. C# - REST API 대신 github 클라이언트 라이브러리를 통해 프로그래밍으로 접근
12600정성태4/15/202116794.NET Framework: 1039. C# - Kubeconfig의 token 설정 및 인증서 구성을 자동화하는 프로그램
12599정성태4/14/202117562.NET Framework: 1038. C# - 인증서 및 키 파일로부터 pfx/p12 파일을 생성하는 방법파일 다운로드1
12598정성태4/14/202118141.NET Framework: 1037. openssl의 PEM 개인키 파일을 .NET RSACryptoServiceProvider에서 사용하는 방법 (2)파일 다운로드1
12597정성태4/13/202117728개발 환경 구성: 569. csproj의 내용을 공통 설정할 수 있는 Directory.Build.targets / Directory.Build.props 파일
12596정성태4/12/202117063개발 환경 구성: 568. Windows의 80 포트 점유를 해제하는 방법
12595정성태4/12/202116808.NET Framework: 1036. SQL 서버 - varbinary 타입에 대한 문자열의 CAST, CONVERT 변환을 C# 코드로 구현
12594정성태4/11/202116265.NET Framework: 1035. C# - kubectl 명령어 또는 REST API 대신 Kubernetes 클라이언트 라이브러리를 통해 프로그래밍으로 접근 [1]파일 다운로드1
12593정성태4/10/202117306개발 환경 구성: 567. Docker Desktop for Windows - kubectl proxy 없이 k8s 대시보드 접근 방법
12592정성태4/10/202116810개발 환경 구성: 566. Docker Desktop for Windows - k8s dashboard의 Kubeconfig 로그인 및 Skip 방법
12591정성태4/9/202120725.NET Framework: 1034. C# - byte 배열을 Hex(16진수) 문자열로 고속 변환하는 방법 [2]파일 다운로드1
12590정성태4/9/202116862.NET Framework: 1033. C# - .NET 4.0 이하에서 Console.IsInputRedirected 구현 [1]
12589정성태4/8/202118092.NET Framework: 1032. C# - Environment.OSVersion의 문제점 및 윈도우 운영체제의 버전을 구하는 다양한 방법 [1]
... 46  47  48  49  50  51  52  [53]  54  55  56  57  58  59  60  ...