ODE 시스템의 솔루션에서 최대한의 정확도를 얻기 위해 장기간 시뮬레이션을하고 있습니다. 4 배 (128 비트) 정밀도 계산과 2 배 (64 비트) 정밀도를 비교하는 시간을 확인하려고합니다. 몇 번 봤는데 몇 가지 의견을 봤어 : 일부는 4 배 더 오래 걸릴거야, 다른 말은 60-70 배 걸릴거야. 그래서 내 자신의 문제를 해결하기로 결심했다. 간단한 포트란 벤치 마크 프로그램을 작성했다.CPU 시간이 4 배 대 배정
전형적인 실행의program QUAD_TEST
implicit none
integer,parameter :: dp = selected_int_kind(15)
integer,parameter :: qp = selected_int_kind(33)
integer :: cstart_dp,cend_dp,cstart_qp,cend_qp,crate
real :: time_dp,time_qp
real(dp) :: sum_dp,sqrt_dp,pi_dp,mone_dp,zero_dp
real(qp) :: sum_qp,sqrt_qp,pi_qp,mone_qp,zero_qp
integer :: i
! ==============================================================================
! == TEST 1. ELEMENTARY OPERATIONS ==
sum_dp = 1._dp
sum_qp = 1._qp
call SYSTEM_CLOCK(count_rate=crate)
write(*,*) 'Testing elementary operations...'
call SYSTEM_CLOCK(count=cstart_dp)
do i=1,50000000
sum_dp = sum_dp - 1._dp
sum_dp = sum_dp + 1._dp
sum_dp = sum_dp*2._dp
sum_dp = sum_dp/2._dp
end do
call SYSTEM_CLOCK(count=cend_dp)
time_dp = real(cend_dp - cstart_dp)/real(crate)
write(*,*) 'DP sum: ',sum_dp
write(*,*) 'DP time: ',time_dp,' seconds'
call SYSTEM_CLOCK(count=cstart_qp)
do i=1,50000000
sum_qp = sum_qp - 1._qp
sum_qp = sum_qp + 1._qp
sum_qp = sum_qp*2._qp
sum_qp = sum_qp/2._qp
end do
call SYSTEM_CLOCK(count=cend_qp)
time_qp = real(cend_qp - cstart_qp)/real(crate)
write(*,*) 'QP sum: ',sum_qp
write(*,*) 'QP time: ',time_qp,' seconds'
write(*,*)
write(*,*) 'DP is ',time_qp/time_dp,' times faster.'
write(*,*)
! == TEST 2. SQUARE ROOT ==
sqrt_dp = 2._dp
sqrt_qp = 2._qp
write(*,*) 'Testing square root ...'
call SYSTEM_CLOCK(count=cstart_dp)
do i = 1,10000000
sqrt_dp = sqrt(sqrt_dp)
sqrt_dp = 2._dp
end do
call SYSTEM_CLOCK(count=cend_dp)
time_dp = real(cend_dp - cstart_dp)/real(crate)
write(*,*) 'DP sqrt: ',sqrt_dp
write(*,*) 'DP time: ',time_dp,' seconds'
call SYSTEM_CLOCK(count=cstart_qp)
do i = 1,10000000
sqrt_qp = sqrt(sqrt_qp)
sqrt_qp = 2._qp
end do
call SYSTEM_CLOCK(count=cend_qp)
time_qp = real(cend_qp - cstart_qp)/real(crate)
write(*,*) 'QP sqrt: ',sqrt_qp
write(*,*) 'QP time: ',time_qp,' seconds'
write(*,*)
write(*,*) 'DP is ',time_qp/time_dp,' times faster.'
write(*,*)
! == TEST 3. TRIGONOMETRIC FUNCTIONS ==
pi_dp = acos(-1._dp); mone_dp = 1._dp; zero_dp = 0._dp
pi_qp = acos(-1._qp); mone_qp = 1._qp; zero_qp = 0._qp
write(*,*) 'Testing trigonometric functions ...'
call SYSTEM_CLOCK(count=cstart_dp)
do i = 1,10000000
mone_dp = cos(pi_dp)
zero_dp = sin(pi_dp)
end do
call SYSTEM_CLOCK(count=cend_dp)
time_dp = real(cend_dp - cstart_dp)/real(crate)
write(*,*) 'DP cos: ',mone_dp
write(*,*) 'DP sin: ',zero_dp
write(*,*) 'DP time: ',time_dp,' seconds'
call SYSTEM_CLOCK(count=cstart_qp)
do i = 1,10000000
mone_qp = cos(pi_qp)
zero_qp = sin(pi_qp)
end do
call SYSTEM_CLOCK(count=cend_qp)
time_qp = real(cend_qp - cstart_qp)/real(crate)
write(*,*) 'QP cos: ',mone_qp
write(*,*) 'QP sin: ',zero_qp
write(*,*) 'QP time: ',time_qp,' seconds'
write(*,*)
write(*,*) 'DP is ',time_qp/time_dp,' times faster.'
write(*,*)
end program QUAD_TEST
결과, 어떤 최적화 플래그없이, gfortran 4.8.4
로 컴파일 후 :
Testing elementary operations...
DP sum: 1.0000000000000000
DP time: 0.572000027 seconds
QP sum: 1.00000000000000000000000000000000000
QP time: 4.32299995 seconds
DP is 7.55769205 times faster.
Testing square root ...
DP sqrt: 2.0000000000000000
DP time: 5.20000011E-02 seconds
QP sqrt: 2.00000000000000000000000000000000000
QP time: 2.60700011 seconds
DP is 50.1346169 times faster.
Testing trigonometric functions ...
DP cos: -1.0000000000000000
DP sin: 1.2246467991473532E-016
DP time: 2.79600000 seconds
QP cos: -1.00000000000000000000000000000000000
QP sin: 8.67181013E-0035
QP time: 5.90199995 seconds
DP is 2.11087275 times faster.
뭔가 일이 일어나고해야합니다. 내 생각에 sqrt
은 최적화 된 알고리즘을 통해 gfortran
으로 계산됩니다. 이는 아마도 4 배 정밀도 계산을 위해 구현되지 않았을 것입니다. sin
및 cos
의 경우는 그렇지 않을 수 있지만 기본 작동은 왜 4 배 정밀도에서 7.6 배 느려지는 반면 삼각 함수에서는 2 배만큼 느려 집니까? 삼각 함수에 사용 된 알고리즘이 쿼드 및 배정도에서 동일하면 CPU 시간이 7 배 증가 할 것으로 예상됩니다.
64 비트에 비해 128 비트 정밀도를 사용하면 과학 계산의 평균 속도가 느려 집니까?
저는 인텔 i7-4771 @ 3.50GHz에서 실행하고 있습니다.
멀티 코어 시스템에서 'CPU_TIME'을 사용하지 마십시오. 한 코어에서 시작 시간을, 다른 코어에서 종료 시간을 가져갈 수 있습니다. 이 시간은 상관 관계가 없으므로 아무 것도 얻을 수 없습니다. 'system_clock'을 사용하면이 문제가 해결됩니다. –
[여기] (https://stackoverflow.com/questions/25465101/fortran-parallel-programming/25465290#25465290) 및 [여기] (https://stackoverflow.com/questions/6878246/fortran-intrinsic- 타이밍 - 루틴 - 어느 것이 더 나은 cpu-time-or-system-clock인지). –
Thanks @ AlexanderVogt, 나는 SYSTEM_CLOCK을 사용하기 위해 게시물을 편집했다. – LeWavite