GCC가 a*a*a*a*a*a를 (a*a*a)*(a*a*a)로 최적화하질 않습니다.
조회수 2537회
발생하는 문제 및 실행환경
컴파일러가 pow(a,2)
는 a*a
로 최적화하는 걸로 알고 있는데
pow(a,6)
는 최적화하지 않고 라이브러리 함수 pow()
를 부릅니다.
C++ 인텔 컴파일러는 6까지 최적화해주는데 왜 GCC C컴파일러는 2는 최적화하면서 6은 최적화하지 않나요?
궁금해서 GCC 4.5.1에 "-O3 -lm -funroll-loops -msse4" 옵션으로 pow(a,6)
자리에 a*a*a*a*a*a
를 넣어 봤을 때는 이렇게
movapd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
나온 반면에 (a*a*a)*(a*a*a)
를 쓰니까 훨씬 더 빨리 실행됐습니다.
movapd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm14, %xmm13
mulsd %xmm13, %xmm13
컴파일러가 왜 최적화를 안하죠?
1 답변
-
부동소수점 연산은 컴퓨터 수학의 관점에서는 결합 법칙이 성립하지 않습니다.
그래서
a*a*a*a*a*a
와(a*a*a)*(a*a*a)
가 다른 결과를 낼 수 있기 때문에 컴파일러가 최적화를 하지 않습니다.제 컴퓨에서 실험해봐도
int main(){ float a = 3.9989391; printf("%f\n", a*a*a*a*a*a); printf("%f\n", (a*a*a)*(a*a*a)); }
출력 :
4089.485840 4089.485596
둘이 다른 결과를 냅니다.
속도를 빨리하기 위해서 약간의 오차를 허용한다면 컴파일러에 옵션
-fassociative-math
이나-ffast-math
를 줄 수 있습니다.
댓글 입력