템플릿 작업시 점점 더 긴 컴파일 시간을 어떻게 처리합니까?


13

Visual Studio 2012를 사용하고 있으며 "심점"을 도입하기 위해 템플릿 매개 변수를 클래스 "just"에 추가하여 단위 테스트에서 해당 부분을 모의 객체로 바꿀 수있는 경우가 있습니다.

C ++에서 일반적으로 심 포인트를 어떻게 도입합니까? 템플릿 매개 변수를 사용하여 인터페이스를 사용하거나 암묵적 인터페이스와 일부 기준을 기반으로 혼합하는 방법은 무엇입니까? 한 가지 C ++ 파일 (템플릿 파일을 포함하고 다른 템플릿을 포함 할 수도 있음)을 컴파일 할 때 개발자 컴퓨터에서 약 5-10 초 정도 걸리는 객체 파일이 생성되기 때문에이를 묻는 한 가지 이유도 있습니다. .

VS 컴파일러는 내가 이해하는 한 템플릿을 컴파일하는 데 특히 빠르지 않으며 템플릿 포함 모델로 인해 템플릿을 실제로 사용하는 모든 파일에 템플릿 정의 를 실제로 포함하고 수정할 때마다 해당 템플릿을 다시 인스턴스화 할 수 있습니다 해당 템플릿과 관련이없는 것) 컴파일 시간에 문제가있을 수 있습니다 (증분 컴파일을 수행 할 때).

템플릿으로 작업 할 때 (더 좋거나 빠른 컴파일러 외에도 :-) 컴파일 시간을 늘리고 컴파일 시간을 처리하는 방법은 무엇입니까?


1
@RobertHarvey 종속성 주입은 템플릿 매개 변수를 사용하여 수행됩니다. 이것을 인스턴스화하는 프로덕션 코드에서 컴파일 시간이 느립니다.
Ghita

5
C ++ 11을 사용하고 있습니까? 참조 en.wikipedia.org/wiki/C%2B%2B11#Extern_template
mike30

2
Andrei Alexandrescu는 "Modern C ++ design"을 작성 했으므로 많은 C ++ 프로그래머는 모든 것에 템플릿을 사용해야하고 컴파일러가 최대한 처리해야한다고 생각합니다. 그것은 일반적으로 당신이 묘사하는 효과로 이어집니다. 이전에는 (현재는 여전히 다른 언어를 사용하는 프로그래머에게는) 최종 사용자를 위해 CPU 사이클이 더 필요할 때에도 템플릿을 사용하지 않고 런타임 메커니즘을 사용한 종속성 주입과 같은 것을 처리하지 않는 것이 좋습니다. ). 솔직히 Robert가 100 % 정확하다고 생각합니다.
Doc Brown

1
@Ghita : 템플릿 메타 프로그래밍을 사용하는 IMHO는 STL과 같은 라이브러리를 비슷한 요구 사항으로 작성하지 않는 한 종종 조기 최적화의 형태 일뿐입니다. 컴파일 시간이 길고 유지 관리 성이 떨어지며 이해하기 어려운 오류 메시지가 많으면 성능이 약간 떨어집니다. "외부 템플릿"을 사용하면 단기적으로 도움이 될 수 있지만, 만약 내가 신발을 신었다면 장기적인 개선에 대해서도 생각할 것입니다.
Doc Brown

4
@DocBrown. 반대로, 빌드 성능을 향상시키기 위해 템플릿을 피하는 것이 조기 최적화 라고 말할 수 있습니다. 템플릿은 많은 문제에 대한 이상적인 추상화입니다.
mike30

답변:


9

경우 템플릿 매개 변수는 유한 (소) 값의 집합을 가정 할 수있다, 당신은 소스 파일에 자신의 정의를 이동하고 사용할 수있는 명시 적 인스턴스화 .

예를 들어,에 aaa.h당신만을 템플릿 함수를 선언 f하고 g:

template <int n>
int f();

template <class T>
void g(int a);

가정 n템플릿 매개 변수는 1, 3, 6 일 수 있으며, T템플릿 파라미터 만 될 수있다 int, longvoid *.

그런 다음 다음 aaa.cpp과 같이 정의 하십시오.

template <int n>
int f()
{
    ...
}

template <class T>
void g(int a)
{
    ...
}

template int f<1>();
template int f<3>();
template int f<6>();

template void g<int>(int a);
template void g<long>(int a);
template void g<void *>(int a);

이러한 방식으로 컴파일러는 컴파일 할 때 지정된 매개 변수에 대한 템플리트를 인스턴스화합니다 aaa.cpp. 클라이언트 코드를 컴파일 할 때 정의가 어딘가에 있다고 가정하고 링커가이를 처리합니다.

#include "aaa.h"

int main()
{
    f<1>();
    f<3>();
    f<6>();

    g<int>(5);
    g<long>(5);
    g<void *>(5);
}

템플릿 클래스를 명시 적으로 인스턴스화 할 수도 있습니다. 단점은 다른 템플릿 매개 변수를 사용 f하거나 사용할 수 없다는 것 g입니다.

#include "aaa.h"

int main()
{
    f<5>();
}

결과

undefined reference to `int f<5>()'

소수 (<10) 정수 템플릿 매개 변수 세트에 의존하는 복잡한 클래스가 거의없는 프로젝트 에서이 기술을 사용했으며 컴파일 시간이 크게 단축되었습니다 (컴파일러가 클라이언트 코드를 컴파일 할 때 복잡한 템플릿 정의를 구문 분석 할 필요가 없기 때문에) . 물론 실제 코드에 따라 성능이 약간 떨어질 수 있습니다.


2

비슷한 문제에 대해 이상한 해결책을 사용하면 STL을 포함하면 소스 파일 당 몇 초와 같은 컴파일 시간이 포함됩니다. 그래서 모든 소스 파일을 하나의 마스터 파일에 포함 시켰고 파일 당 컴파일 시간이 거의 바뀌지 않았습니다.

디자인을 깨끗하게 유지하기 위해 makefile을 계속 유지했지만 실제로는 사용하지 않았습니다 (아직 작동하는지 확인 제외).


0

우리는 사전 컴파일 된 헤더와 사전 컴파일 된 템플릿을 하룻밤 사이에 구축하고 다음 날에 대비하여 큰 작업을 시작했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.