부동소수점 계산시 곱하기가 나누기보다 빠르다는 얘기를 듣고서 실제로 어떤지 측정해봤다.
환경은 AMD A8-3870 + Windows 10 + Visual Studio 2015.
측정 내용은 간단하다.
1. x *= 2, x *= 3, x /= 2, x /= 3을 10억번씩 반복 수행한 뒤 시간을 측정
2. 같은 연산을 부동소수점 및 정수에 대하여 곱하기, 나누기 및 더하기 각각 수행 (x *= 2.0, x *= 2, x /= 0.5, x += x)
3. float, double에서 각각 수행
4. 수행시 /fp:precise(기본)과 /fp:fast를 지정
1. x *= 2
사실상 별 차이 없다. 아래 그래프를 언뜻 보면 차이가 있어보이지만, 측정 결과는 최대 0.01초밖에 차이나지 않는다.
2. x *= 3
곱하기 대신 나누기로 처리하는 경우 처리 시간이 늘어난다.
기본값인 /fp:precise로 지정한 경우 시간이 훨씬 더 걸리며, double 쪽이 더 많이 걸린다.
3. x /= 2
큰 차이는 없고, 미미하지만 float가 double보다 빠르기는 함
4. x /= 3
x /= 3.0과 x /= 3은 실행 시간이 동일하다.
그리고, x *= 0.333333333333 쪽이 훨씬 빠르다.
5. 결론
위의 결과를 한 그래프로 보면 아래와 같다.
대략 아래와 같이 정리할 수 있다.
1. 전체적으로 연산에 소요되는 시간은 거의 동일함
2. int와 부동소수점 간의 시간차이는 없음
3. 일부 연산에서는 /fp:precise에서 시간이 더 소요되며, 이 경우엔 double이 float보다 더 걸리고, 나눗셈이 곱셈보다 더 걸림.
6. 근데 /fp:precise가 뭐임?
부동소수점 연산은 실수 연산과는 다소 차이가 있어, 수학적인 무결성을 보장하지 않는다.
즉, 아래와 같은 상식적인 식이 틀리는 경우가 있을 수 있다.
\(a + b + c = (a+b) + c = a + (b+c)\)
\((a \times b) \times c = a \times (b \times c)\)
/fp:precise를 지정하면 이런 문제를 예방하기 위해 컴파일시 최적화하는 과정에서 식을 별도로 최적화하지 않는다.
/fp:fast를 지정하면 최적화 추가 실시.
좀 더 자세한 내용은 다음 글들을 참조하면 된다.
1. MSDN: /fp (Specify Floating-Point Behavior)
2. Consistency of Floating - Point Results using the Intel® Compiler or Why doesn’t my application always give the same answer?