회사에서 CI ((Continuous Integration; 지속통합)) 서버 설정을 고치다가 문뜩 든 의문.
왜 MS에서 제공하는 툴들은 C/C++에서 파일단위의 병렬 컴파일을 지원하지 않을까? VisualStudio 2005 / .NET Framework 2.0까지의 툴만 가지고 할 수 있는 빌드 병렬화는 한가지 뿐이다.
2개 이상의 프로젝트가 하나의 솔루션에 물려있을 때, devenv (IDE를 감싸는 쉘로 생각하면 된다) 는 프로젝트간의 dependency (의존관계)를 분석해서 동시에 빌드해도 될 프로젝트는 동시에 빌드한다. 그리고 빌드라는 작업 혹은 어떤 스케쥴링 작업의 특성상 그래프 자체는 DAG ((directed acyclic graph. 방향성이 있고, cycle(or loop)는 없는 그래프. 이런 그래프로 표현될 수 있는 작업이면 자연스러운 방법의 순서를 만들 수가 있다.)) 로 나올 수 밖에 없고
이런 프로젝트가 있으면 {ut, lib2, lib1} 을 동시에 빌드하고, {test, app}을 동시에 빌드할 수 있다. 그리고 가지고 있는 CPU 코어 수에 맞춰서 해당 작업을 수행한다. (즉 .proj 파일 단위의 병렬화)
근데 이걸 MSBuild 라는 MS에서 내놓은 XML 설정 파일 기반의 빌드 툴 (C++, C#, …, 그리고 임의 파일 실행 등등을 포함하는) 을 사용해서 빌드하면 CPU 코어를 1개만 사용하는 삽질스러운 동작을 한다.
반면에 이미 나온지 수십년(…)이 지난 케케묵은 툴인 make 의 경우엔 저보다 나은 병렬화를 수행한다.
make -j2 Makefile
같은 명령을 하면 -j 뒤에 입력한 숫자만큼의 CPU 코어를 사용해서 빌드작업을 진행한다. 어차피 이 작업도 makefile 안의 dependency를 분석해서 DAG 를 정렬해서 나올 수 있는 순서에 따라서 병렬로 컴파일을 수행한다. 이 경우에는 project 같은 개념이 없으니 파일 단위의 병렬화가 된다. 게다가 이 경우엔 링커를 제외하고는 의존성이 매우 간단하기 때문에, 병렬성이 매우 높다.
병렬성을 높일 수 있기 때문에, IncrediBuild 같은 대규모 분산 빌드 툴들의 경우에도 파일 단위로 여기저기서 컴파일해서 링크하게 해준다(…).
내가 의문인 것은 MS에서 왜 이런 병렬성을 활용하려고 하지 않는가 하는 것. 물론 서버용으로 많이 사용되었고, 그래서 다중 프로세서 시스템에도 자주 사용되던 UNIX의 make 유틸리티가 다중 CPU 를 지원하는 것은 상당히 자연스러운 일이다. 그렇지만 CPU 1개짜리 머신에서 출발한 윈도우라곤 해도, 이미 멀티 코어 CPU가 보편화되었고, VisualStudio 자체는 동시에 여러 개의 프로젝트 빌드를 지원하는데 MSBuild는 왜 지원을 안하는지는 좀 의문이었다.
좀 찾아보니 VS 2008 (.NET Framework 3.5) 부터 포함된 MSBuild는 다중 CPU 코어 사용을 지원한다고 한다. 그렇지만 MSBuild 를 만드는 MSBuild Team Blog를 보면 디자인 고려 사항이 있는데,
In addition to thinking about scenarios, we’re working on implementation designs. On the implementation side the build mechanism we are considering is completely declarative. The MSBuild engine will not make any attempt to determine what can be parallelized. Instead, we will instead introduce parallelization “constructs” in the file format that will allow a project or targets file author to indicate what can and cannot be parallelized.
디자인 아이디어를 보니 아무래도 별도 구문 없이는 병렬화가 쉽게 될 것 같지는 않다 -_-;;
MSBuild 3.5 (with .NET 3.5)를 몇 가지를 가지고 병렬 빌드를 시도해봤는데, 일단 현재까지의 경험을 종합해보면,
- 별도 구문없이 solution 파일만 가지고 IDE에서 수행되는 병렬빌드는 안된다
- MSBuild 태스크를 이용해서 .vcproj를 리스팅해서 병렬 빌드가 가능하다. 그렇지만 MSBuild는 C++ 프로젝트를 빌드하게 설정하는게 좀 쥐약 -_-;
- MSBuild 3.5 가지고 .NET 2.0 툴셋을 강제로 쓰게해서 병렬로 VC 2005 프로젝트를 빌드하진 못한다
Win32의 IDE가 이런저런 리소스 빌드하는 것 때문에 복잡한 것은 알겠는데(위에 인용한 부분을 봐도), 그래도 공짜 점심 ((C++ 솔루션을 별도 작업 없이 병렬 빌드하는 것)) 을 바라는건 좀 무린가 -_-;
VS에서도 배치빌드 실행하면 순서대로 빌드하죠. 짜증;
별도로
http://gpgstudy.com/forum/viewtopic.php?t=17602
VS2005에서 하나의 프로젝트에서도 병렬 컴파일을 걸 수 있습니다. 솔루션 성격에 따라 쓸만한 경우가 있겠더군요.
/MP 옵션이 2005에도 적용되는 거군요. 좋은 정보 감사합니다 :)
생각해보니 정말 필요한 건데 모르고 살고 있었네요 (…)
정말 필요했던 건지는 모르겠는데, 이제 필요한 시대랄까 :)
UNIX 서버 쪽이야 예전부터 CPU수가 많아서 저런 옵션이 있는게 편했지만, 윈도우 환경에 다수의 코어가 들어온지는 얼마 안 지났으니까