2011-03-29 2 views
3

컴파일러가 소스 코드를 최적화하기 위해 수행하는 작업 목록이 있다면 누구에게 알 수 있습니까? 나는 예로써 GCC를 선호한다.컴파일러가 최적화를 수행하도록 돕는 코드 작성

좋은 최적화를 얻고 컴파일러가 최적화 할 수 있도록 프로그래머가 코드와 관련하여 무엇을해야하는지 알고 싶습니다. 프로그래머가 최적화를 수행하면 컴파일러가 더 나은 최적화를 수행하지 않을 수 있습니다.

예 :

replace 
for (int i = 0; i < n - 1; i++) 
by 
int n2 = n - 1; 
for (int i = 0; i < n2; i++) 


for (int i = 0; i < n/2; i++) 
by 
int n2 = n/2; 
for (int i = 0; i < n2; i++) 



for (int i = 0; i < obj.calc_value(); i++) //calc_value() will return the same result with obj remaining unchanged. 
by 
int y = obj.calc_value() 
for (int i = 0; i < y; i++) 

이 읽고 이해할 수있는 코드를 간단하게 유지하는 것이 중요합니다.

감사

편집 :

다른 예 :

  • 인라인 함수
  • 제거 재귀 진심으로
+0

컴파일러도 사람들입니다! :-) 코드가 읽기 쉽고 이해하기 쉬운 경우, 사용자의 의도를보고 코드를 생성합니다. 이전에 보지 못했던 "똑똑한 트릭"을한다면, 당신의 동료들도 컴파일러도 그걸로 무엇을해야하는지 알지 못할 것입니다. –

답변

13

, 단지 컴파일러에 그를 둡니다. 나는 "미친"-O3 레벨에서 gcc가 출력하는 코드를 보았고 이러한 최적화 엔진을 작성한 사람들은 외계인이거나 실질적으로 먼 미래의 시간이라는 사실을 입증했습니다.

register 또는 inline이 내 코드의 성능에서 상당한 차이를 보인 상황을 아직 보지 못했습니다. 그것이 을 의미하지는 않습니다. 컴파일러 작성자는 프로세서에서 마지막으로 온스의 성능을 추출 할 때 단순한 필사자보다 훨씬 더 많은 트릭을 알고 있습니다.

최적화가 진행되는 한 실제 문제가있는 경우에만 수행해야합니다. 이는 코드를 프로파일 링하고 병목 현상을 발견하는 것입니다.하지만 더 중요한 것은 컨텍스트가 느린 것으로 간주되지 않는 작업을 최적화하지 않는다는 것입니다. 원샷 작업이 10 분의 1 초 또는 100 분의 1이 걸릴지 여부는 사용자와의 차이가 없습니다.

그리고 때때로는 가독성을위한 최적화는 당신이 옆으로


:-)이 gcc가 당신을 위해 수행하는 멋진 트릭 단지 하나이다 할 수있는 최선의 하나입니다. 맞아

main: pushl %ebp   ; stack frame setup. 
     movl  $720, %eax  ; just load 720 (6!) into eax. 
     movl  %esp, %ebp  ; stack frame 
     popl  %ebp   ; tear-down. 
     ret      ; and return. 

는, GCC 그냥 컴파일 시간에 그것을 모두 밖으로 작동합니다

static int fact (unsigned int n) { 
    if (n == 0) return 1; 
    return n * fact (n-1); 
} 
int main (void) { 
    return fact (6); 
} 

이 (-O3에서)로 컴파일 : 그것을 계승을 계산하고 반환하도록되어 다음과 같은 코드를 살펴 보자 -O0 (순진) 버전

int main (void) { return 720; } 

명암이 :와 동등한로 전체를 회전

main: pushl %ebp    ; stack 
     movl %esp, %ebp   ; frame 
     andl $-16, %esp   ; set 
     subl $16, %esp   ; up. 
     movl $6, (%esp)   ; pass 6 as parameter. 
     call fact    ; call factorial function. 
     leave      ; stack frame tear down. 
     ret      ; and exit. 

fact: pushl %ebp    ; stack 
     movl %esp, %ebp   ; frame 
     subl $24, %esp   ; set up. 
     cmpl $0, 8(%ebp)  ; passed param zero? 
     jne  .L2    ; no, keep going. 
     movl $1, %eax   ; yes, set return to 1. 
     jmp  .L3    ; goto return bit. 

.L2: movl 8(%ebp), %eax  ; get parameter. 
     subl $1, %eax   ; decrement. 
     movl %eax, (%esp)  ; pass that value to next level down. 
     call fact    ; call factorial function. 
     imull 8(%ebp), %eax  ; multiply return value by passed param. 

.L3: leave      ; stack frame tear down. 
     ret      ; and exit. 
+5

+1은 "가독성을 최적화하기위한 최선의 방법"입니다. 최신 컴파일러가 수행하는 최적화 유형에 대한 문서를보고 싶습니다. 나는 (루프 언 롤링, 스택보다는 레지스터 사용, 인라인, 꼬리 재귀 풀기 해제 등) 몇 가지를 읽었지만 모두 분명하고 고대적인 트릭이다. –

+1

@Merlyn Morgan-Graham :이 책은 매우 가치 있다고 생각합니다 (컴파일러를 작성하는 경우) [고급 컴파일러 디자인 구현] (http://www.amazon.com/Advanced-Compiler-Design-Implementation-Muchnick/dp/ 1558603204/ref = pd_rhf_shvl_3)하지만이 책을 구입 한 지 오래되었으므로 현대 책이 더 많을 것이라고 확신합니다. –

+0

그래서 루프 상태에서도'n - 1'을 최적화 할 수있을 것 같네요? :-) –

3

권장 개선 사항은 모든 최적화 컴파일러가 수행하는 기본 최적화 인 Loop-invariant code motion의 예입니다.

실제 컴파일러가 수행하는 최적화 범위는이 예제보다 훨씬 앞선 것입니다. 위에 링크 된 Wikipedia 기사에는 추가 읽기를위한 링크가 있습니다.

+0

+1 그가 물어 본 특정 최적화를 식별하고 처리합니다. –

0

게시 한 코드는 paxdiablo의 답변에 동의합니다. 컴파일러는 많은 경우 힌트없이 아주 잘 최적화 할 수 있습니다.

템플릿 메타 프로그래밍은

컴파일러의 최적화에 도움 (그리고에 이유가있다! - 프로필, 프로필, 프로파일)을 찾고 있다면, 내가 본 것 중 가장 잠재적으로 유용한 트릭 template metaprogramming이다.

Boost has some direct support for template metaprogramming.

유용한 예제는 소스 코드에 이러한 연산을 남기면서 수행되는 작업 수를 줄이는 템플릿 메타 프로그래밍 된 행렬 수학 라이브러리입니다. 또한 컴파일 타임에 일부 작업을 완전히 평가합니다.

가 여기에 구글에 나타 것들의 첫 번째입니다 : http://arma.sourceforge.net/

헌장 정확성

쉽게 코드 버그 방지를 도울 수 있기 때문에 당신이 조사해야하는 또 다른 일을, const-correctness입니다. 추가 혜택은 it can sometimes help with compiler optimizations입니다.

const-correctness와 template-metaprogramming 모두 매우 익숙하기는하지만 매우 유용합니다. C++의 대부분입니다 :)

0

여기서 "옵티 마이저를 사용하지 마십시오"라고 말하면 컴파일러가 더 나은 코드를 생성 할 수 있도록 도와 줄 수 있습니다.

컴파일러는 전술적으로 코드를 주문할 때 대부분의 프로그래머보다 사용 가능한 파이프 라인과 실행 장치를 가장 효율적으로 사용할 수 있습니다. 그런데, 컴파일러가 전략적 프로그래밍 레벨, 즉 개별 절차 이상의 수준에서는 그리 좋지 않다는 것을 지적하는 것도 중요합니다.

실적이 저조한 소프트웨어는 실적이 우수한 것보다 훨씬 일반적입니다. "옵티 마이저를 사용하지 마십시오"가 거의 인정하지 않는 것 (그리고 확실히 귀하의 게시물에 대한 대답이 아님)은 실적이 저조한 소프트웨어를 작성할 수 있으므로 (분명히) 실적이 좋을 수도 있습니다. 컴파일러는 연금술이 아닙니다 : 쓰레기 소스 코드를 피드하면 쓰레기 기계 코드가 생깁니다. 유능한 소스 코드를 제공하면 유능한 시스템 코드가 확실히 생성됩니다.

저는 최적화 주제에 대해 모호합니다. 한편으로 성능 문제가 정확히 지적되면 (대부분 개발이 완료 될 때), 전략적 수준에서 작업해야하기 때문에 (예 : 100 % 이상) 상당한 개선이 이루어지기에는 너무 늦습니다. 에 대한 시간). 다른 한편, 이전에 완료된 경우 "전체 성능 그림"을 사용할 수 없으므로 "최적화 안 함"은 유효한 데이터가 없기 때문에 최적화하기에 너무 이르다고 말합니다. 최적화는 너무 빈약하게 구성된 소프트웨어를 구제하기 위해 공황 상태로 수행되거나 수락 테스트를 통해 평생 지원되는 경우가 종종 있습니다. 긍정적 인 맥락에서의 최적화 (좋은 코드를보다 효율적으로 실행)는 어느 정도 전례가 없습니다 (적어도 여기서는?).

나는 잘 수행하는 코드를 작성하는 문제를 즐긴다. 내 코드는 읽을 수 있지만 처음 경험을 통해 특정 코드 구문을 선택합니다. 왜냐하면 코드가 더 잘 수행된다는 것을 알고 있기 때문입니다.또한 개발 초기부터 응용 프로그램을 측정하여 스스로 측정 한 다음 개발이 진행됨에 따라 성능을 주시 할 수 있습니다.

관련 문제