작은 보정 도구인데 코드는 아래에 있어요. 출력은 맞는데 너무 느려요. detrend+clip은 몇 초씩 걸리고, rms도 원래보다 느려요. 요소당 곱셈 한 번, 덧셈 한 번뿐인데도요. -O3랑 -march=native를 써봤는데 별로 달라지지 않았어요. Apple silicon에서 sum이랑 real(dp)가 문제인가 의심했어요. 이 느린 두 단계는 같은 문제일까요, 다른 문제일까요? 왜 이렇게 오래 걸리는지 모르겠어요.
Makefile
FC = gfortran
FFLAGS = -O3 -march=native -g
sensor_cal: src/sensor_mod.f90 src/main.f90
$(FC) $(FFLAGS) -o $@ $^
clean:
rm -f sensor_cal *.mod
src/sensor_mod.f90
module sensor_mod
implicit none
integer, parameter :: dp = kind(1.0d0)
contains
! remove the mean of one record (all channels at one time step)
subroutine detrend_record(v, n)
integer, intent(in) :: n
real(dp), intent(inout) :: v(n)
real(dp) :: m
m = sum(v) / n
v = v - m
end subroutine detrend_record
subroutine clip_record(v, n, lim)
integer, intent(in) :: n
real(dp), intent(inout) :: v(n)
real(dp), intent(in) :: lim
integer :: k
do k = 1, n
if (v(k) > lim) v(k) = lim
if (v(k) < -lim) v(k) = -lim
end do
end subroutine clip_record
function channel_rms(a, nrec, nchan) result(r)
integer, intent(in) :: nrec, nchan
real(dp), intent(in) :: a(nrec, nchan)
real(dp) :: r(nchan)
integer :: i, j
r = 0.0_dp
do i = 1, nrec
do j = 1, nchan
r(j) = r(j) + a(i, j)**2
end do
end do
r = sqrt(r / nrec)
end function channel_rms
end module sensor_mod
src/main.f90
program sensor_cal
use sensor_mod
implicit none
integer :: nrec, nchan, i, t0, t1, rate
real(dp), allocatable :: readings(:,:), rms(:)
character(len=32) :: arg
logical :: verbose
verbose = .false.
nrec = 200000
nchan = 64
if (command_argument_count() >= 1) then
call get_command_argument(1, arg)
read(arg, *) nrec
end if
if (command_argument_count() >= 2) then
call get_command_argument(2, arg)
read(arg, *) nchan
end if
if (command_argument_count() >= 3) verbose = .true.
allocate(readings(nrec, nchan), rms(nchan))
call random_number(readings)
readings = 100.0_dp * readings
call system_clock(t0, rate)
do i = 1, nrec
call detrend_record(readings(i, :), nchan)
call clip_record(readings(i, :), nchan, 40.0_dp)
if (verbose .and. mod(i, 50000) == 0) print *, 'record', i
end do
call system_clock(t1)
print '(a,f8.3,a)', 'detrend+clip: ', real(t1 - t0) / rate, ' s'
call system_clock(t0)
rms = channel_rms(readings, nrec, nchan)
call system_clock(t1)
print '(a,f8.3,a)', 'rms: ', real(t1 - t0) / rate, ' s'
print '(a,3f10.4)', 'first rms values: ', rms(1:3)
! TODO: write rms to calibration file, format not agreed with the lab yet
end program sensor_cal
어셈블리는 안 봤고 경고도 안 켜봤어요. 위 시간은 정확한 값이 아니라 기억나는 대로 적은 거예요.