g ++ 컴파일 시간을 단축하는 방법 (많은 템플릿을 사용할 때)
이 질문은 다소 이상 할 수 있지만 어떻게 g ++ 컴파일 시간을 단축 할 수 있습니까? 내 C ++ 코드는 부스트와 템플릿을 많이 사용합니다. 헤더 파일에서 가능한 한 많이 이동하고 -j 옵션을 사용했지만 컴파일 (및 링크)하는 데 여전히 시간이 많이 걸립니다.
내 코드를 분석하고 컴파일러의 병목 현상을 지적하는 도구가 있습니까? 아니면 어떻게 든 내 코드에서 실행되는 컴파일러를 프로파일 할 수 있습니까? 가끔은 컴파일러 콘솔 로그를 쳐다 보느라 너무 많은 시간을 보낸다는 인상을 받기 때문에 정말 좋을 것입니다.
나에게 가장 유용했던 것 :
- RAM 파일 시스템에서 빌드하십시오. 이것은 Linux에서 사소한 일입니다. RAM 파일 시스템에 공통 헤더 파일 (미리 컴파일 된 파일 또는 실제 .h 파일)의 복사본을 보관할 수도 있습니다.
- 미리 컴파일 된 헤더 . (주요) 라이브러리 (예 : Boost, Qt, stdlib) 당 하나씩 있습니다.
- 가능한 경우 포함 클래스 대신 선언하십시오. 이렇게하면 종속성이 감소하므로 헤더 파일을 변경할 때 다시 컴파일해야하는 파일 수가 줄어 듭니다.
- make를 병렬화합니다 . 이것은 일반적으로 사례별로 도움이되지만 전
-j3
세계적으로 만들었습니다. 그래도 Makefile에서 종속성 그래프가 올바른지 확인하십시오. 그렇지 않으면 문제가있을 수 있습니다. -O0
실행 속도 나 코드 크기를 테스트하지 않는 경우에 사용 합니다 (그리고 컴퓨터가 (아마도 작은) 성능 저하에 크게 신경 쓰지 않을만큼 충분히 빠릅니다).- 저장할 때마다 컴파일하십시오. 어떤 사람들은 이것을 좋아하지 않지만 오류를 조기에 볼 수 있고 백그라운드에서 수행 할 수 있으므로 작성을 마치고 테스트 할 준비가되었을 때 기다려야하는 시간이 줄어 듭니다.
설명하는 매우 유사한 시나리오 (부스트, 템플릿, gcc)에서 빌드 속도를 높이기 위해 제가 한 작업은 다음과 같습니다.
- NFS와 같은 네트워크 파일 시스템 대신 로컬 디스크에 구축
- 최신 버전의 gcc로 업그레이드
- distcc 조사
- 더 빠른 빌드 시스템, 특히 더 많은 RAM
파일을 컴파일하는 데 몇 분 정도 걸리는 것으로 가정 합니다. 즉, 미리 컴파일 된 헤더 나 로컬 디스크 문제는 문제가 아닙니다.
딥 템플릿 코드 (부스트 등)를 사용한 긴 컴파일 시간은 템플릿 인스턴스화와 관련하여 특히 가변 템플릿이 템플릿 기본 인수로 에뮬레이션 될 때 gcc의 비우호적 인 점근 적 동작에 뿌리를두고 있습니다.
다음은 가변 템플릿의 동기로 컴파일 시간을 단축 한 문서입니다.
cpptruths는이를 위해 gcc-4.5가 훨씬 더 나은 방법과 가변 템플릿으로 얼마나 훌륭하게 작동하는지에 대한 기사를 가지고 있습니다.
IIRC는 의사 변수에 대한 템플릿 기본 매개 변수의 생성을 제한하는 방법을 가지고 있습니다 .'g ++ -DBOOST_MPL_LIMIT_LIST_SIZE = 10 '이 작동해야한다고 생각합니다 (기본값은 20).
업데이트 : 여기에 유용 할 수있는 컴파일 속도를 높이는 일반적인 기술이있는 멋진 스레드도 있습니다.
업데이트 : 이것은 템플릿을 컴파일 할 때의 성능 문제에 관한 것이며, 허용되는 답변은 gcc-4.5도 권장하며 clang도 긍정적 인 예로 언급됩니다.
재 컴파일을 많이하는 경우 ccache 가 도움이 될 수 있습니다. 실제로 컴파일 속도를 높이지는 않지만 어떤 이유로 쓸모없는 재 컴파일을 수행하면 캐시 된 결과를 제공합니다. 잘못된 문제를 해결하는듯한 인상을 줄 수 있지만, 때때로 재 구축 규칙이 너무 복잡해서 실제로 새 빌드 중에 동일한 컴파일 단계를 거치게됩니다.
추가 아이디어 : 코드가 clang으로 컴파일되면 대신 사용 하세요 . 일반적으로 gcc보다 빠릅니다.
다른 사람들이 추가 한 것과 이미하고있는 것 (병렬화 된 빌드, 컴파일러 옵션 등) 외에도 인터페이스를 통해 액세스되는 구현 클래스에서 템플릿을 숨기는 것이 좋습니다. 이는 다음과 같은 수업을 갖는 대신에 의미합니다.
// ClsWithNoTemplates.h file, included everywhere
class ClsWithTemplates
{
ComplicatedTemplate<abc> member;
// ...
public:
void FunctionUsingYourMember();
};
다음이 있어야합니다.
// ClsWithNoTemplates.h file:
class ClsWithTemplatesImplementation; // forward declaration
// definition included in the ClsWithNoTemplates.cpp file
// this class will have a ComplicatedTemplate<abc> member, but it is only
// included in your ClsWithNoTemplates definition file (that is only included once)
class ClsWithNoTemplates
{
ClsWithTemplatesImplementation * impl; // no templates mentioned anywhere here
public:
void FunctionUsingYourMember(); // call impl->FunctionUsingYourMember() internally
};
This changes your OOP design a bit, but it's for the good: including the definition of 'ClsWithNoTemplates' is now fast and you only (pre)compile the definition of 'ClsWithNoTemplates' once.
Aditionally, if you change the implementation code, any code that included ClsWithNoTemplates.h will probably not need to be redefined.
This change should dramatically increase your partial compilation time, and it will also help in the case where your ClsWithNoTemplates is a public interface exported from a library file: since the file is not changed when you only change the implementation, your dependent client code doesn't need to be recompiled at all.
Try the PIMPL technique, this question: What techniques can be used to speed up C++ compilation times?
It'll prevent the compiler from following the chain of header files and implementations every time you need to do something.
If there are a lot of files you can speed up compilation a lot by just having one .cpp file that #includes all the other .cpp files. This of course requires you to be more careful with macros and such that you already have defined per file as they will now be visible to other cpp files.
If there are many files this can reduce compile time a lot.
Instantiate less templates and inline functions. Precompile as much as you can and just link it rather than compiling everything from scratch. Make sure you're using the latest version of GCC.
However, it's a simple fact that C++ is an incredibly complex language and compiling it takes quite some time.
This paper describes a method for compiling template code much like "traditional" non-template object files. Saves compile & link time, with only one line of code overhead per template instantiation.
Usually, the most expensive parts of compilation are (a) reading the source files (ALL of them) and (b) loading the compiler into memory for each source file.
If you have 52 source (.cc) files, each of which #includes 47 #include (.h) files, you are going to load the compiler 52 times, and you are going to plow through 2496 files. Depending on the density of comments in the files, you may be spending a fair chunk of time eating useless characters. (In one organization I have seen, header files varied between 66% and 90% comments, with only 10%-33% of the file being "meaningful". The single best thing that could be done to enhance readability of those files was strip out every last comment, leaving only code.)
Take a long look at how your program is physically organized. See whether you can combine source files, and simplify your hierarchy of #include files.
Decades ago, companies like IBM understood this, and would write their compilers so that the compiler could be handed a list of files to compile, not just one file, and the compiler would only be loaded once.
'Development Tip' 카테고리의 다른 글
preg_match를 사용하여 YouTube 동영상 ID 구문 분석 (0) | 2020.11.25 |
---|---|
import sun.misc.BASE64Encoder 결과 Eclipse에서 컴파일 오류 발생 (0) | 2020.11.25 |
공개적으로는 읽기 전용이지만 전용 setter가있는 Objective-C 속성 (0) | 2020.11.24 |
사용자 지정 메타 데이터 또는 구성을 package.json에 추가합니다. 유효합니까? (0) | 2020.11.24 |
SQL 레코드가 존재하지 않는 경우에만 테이블에 삽입 (0) | 2020.11.24 |