2010-01-25 6 views
9

예를 제안합니다. 조건 계산을 검사하는 데 ~ 60 사이클이 소요되며 컴파일러 자체에서 컴파일 시간에 계산할 수 없습니다.방법 GCC 컴파일러에게 더 많은 가능성이 지점

if (__builtin_expect(almost_always_false_condition,0)) { 
    // do something 
} 

그러나 :

(GCC 4.3)

+0

관련 : http://stackoverflow.com/questions/1668013/can-likely-unlikely-macros-be-used-in-user-space-code –

답변

10

당신이 조건이 코드의 흐름을 정리하기위한 힌트로 주어진 값을 가질 가능성이 있다는 GCC에 제안하고 싶은 경우에, 당신은 __builtin_expect()를 사용해야합니다 __builtin_expect()이 수행하지 않을 상태를 피하는 방법을 찾고 싶다는 생각이들 것입니다.

if (__builtin_expect(fastCheckThatIsTrueIfFullConditionIsTrue,0)) { 
    // most of the time, we don't even get to here, so you don't need 
    // to evaluate the condition 
    if (almostAlwaysFalseCondition) { 
     // do something 
    } 
} 

당신이 우리에게 조건이 무엇인지에 대한 자세한 내용을 말해 줄 수 : 신속 조건에 근접하고 근사치에 해당하는 경우에만 전체 검사를 할 수있는 방법이 있나요?

+0

이 힌트와 예제를 보내 주셔서 감사합니다. 조건은 로깅에 사용되며 필요에 따라 전환 될 수 있습니다. 값은 컴파일 타임에 알려지지 않습니다 (우리는 로깅 및 로그 오프와 함께 두 가지 버전의 바이너리를 가질 수 없습니다). "빠른 검사"는 가능한 경우 이미 완료되었습니다. – Karol

+0

__builltin_expect는 코드 플로우를 어떻게보다 효율적으로 변경합니까? 같은 확장자를 가지고 있지 않은 컴파일러에서이 작업을 수행 할 수있는 이식성있는 방법이 있습니까? – greatwolf

+0

@ 빅터 T .: 아니오, 이것을 수행 할 수있는 휴대용 방법이 없습니다. –

0

설명서에 따르면 gcc는 프로필 기반 최적화를 수행합니다 (또는 수행 할 수 있음). gcc로 해본 적이 없으므로 더 이상의 조언을 드릴 수 없으며 Google을 치는 동안 가치가있을 것입니다.

3

단일 실행 중에 결과가 다를 수있는 경우 부울 연산자의 지연 평가를 사용하여 조건을 값싼 부분과 값 비싼 부분으로 나누고 저렴한 부분을 먼저 실행할 수 있습니다. a == 5을 계산하기 때문에

if (a == 5 && somethingexpensive()) 
{ 
    ... 
} 

somethingexpensive()보다 저렴하고, 거의 항상 false 경우에는 somethingexpensive 절을 평가하는 것을 피한다, 이는 먼저 실행해야합니다.

결과가 프로그램 실행에 대해 일정한 경우 정적 또는 전역 변수에 계산 결과를 저장하여 최적화 할 수 있습니다.

static int result = doevalfunctiononlyonce(); 

if (result) 
{ 
    ....  
} 

이렇게하면 if의 비용을 간단한 메모리 조회로 줄일 수 있습니다. 조건은 다른 프로 시저에서 작업에 대한 응답으로 변경하면

, 당신은 그 과정에서 전역을 업데이트 할 수 있습니다

int condition; 

void appendToList(int a) 
{ 
    list.append(a); 
    if (list.somethingexpensive()) 
    { 
    condition = true; 
    } else 
    { 
    condition = false; 
    } 
} 

void someotherfunction() 
{ 
    // if (list.somethingexpensive()) 
    if (condition) 
    { 
    ... 
    } 
} 

이 유용 someotherfunction가 더 자주 appendtolist 기능보다 더 많이 불려 갔을 경우.

2

우선, else 절 또는 프로그램의 다른 곳에서 몇 사이클을 소비합니까? 당신이 프로파일을 작성하거나 stackshots을받는다면, 그 시험에 적어도 10 %의 시간을 소비하고 있습니까? 그렇지 않다면, 아마도 당신이 먼저보아야 할 더 큰 문제가있을 것입니다.

둘째, 테스트에서 10 %를 초과하여 소비한다면 알고리즘이 50-50 확률에 가까운 결정 포인트를 갖도록 조정할 수 있는지 확인해야합니다. 50-50 결정 지점은 실행될 때 1 비트의 정보를 산출하지만 99-1 결정 포인트는 약 .07 비트 * 만 산출합니다. 즉, CPU 사이클을 비효율적으로 사용합니다.)이 현상의 예는 선형 검색과 이진 검색을 비교하는 경우입니다.

* 이진 결정 포인트가 있고 결과의 확률이 ab 인 경우 정보 산출량 (엔트로피)은 비트 수는 -(a*log(a) + b*log(b))/log(2)입니다.

0

제 생각에는 이러한 종류의 최적화를 수행하는 가장 좋은 방법은 -fprofile-generate-fprofile-use 옵션을 사용하는 것입니다. 이것은 무엇이 가능하고 그렇지 않은지에 대한 정보를 수집하기 위해 대표적인 유스 케이스의 기반을 필요로하지만, 이러한 목적으로 테스트가 사용될 수 있습니다. 다른면에서는 코드가 추악하고 휴대하기 어려운 지시문으로 장식되어 있지 않습니다.

이 두 옵션에 대한 자세한 내용은 https://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/Optimize-Options.html#Optimize-Options을 참조하십시오.

관련 문제