Created
February 16, 2021 14:50
-
-
Save DSCF-1224/28aec8d0173a473f20b6bf382da67d06 to your computer and use it in GitHub Desktop.
Fortranでの整数の偶奇判定はbtestとmodのどちらが高速か
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program main | |
! <module>s to import | |
use, intrinsic :: iso_fortran_env | |
use, non_intrinsic :: mod_is_even | |
use, non_intrinsic :: mod_test | |
! require all variables to be explicitly declared | |
implicit none | |
! constant(s) for this <program> | |
integer(INT32), parameter :: num_sample = 10_INT32 ** 7 | |
integer(INT32), parameter :: num_trial = 10_INT32 ** 4 | |
integer(INT32), parameter :: range_sample = 2_INT32 ** 30 | |
! variable(s) for this <program> | |
integer(INT32), allocatable :: sample(:) | |
! STEP.01 | |
! generate samples to execute the test | |
call generate_sample ( num_sample= num_sample, sample= sample, first= - range_sample, last= range_sample ) | |
! STEP.02 | |
! execute the test | |
call test_method ( is_even= is_even_bit, sample= sample(:), num_trial= num_trial ) | |
call test_method ( is_even= is_even_mod, sample= sample(:), num_trial= num_trial ) | |
end program main |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FCFLAGS = -ffree-line-length-none -O2 -pedantic -std=f2008 -Wall -Wextra # -fbacktrace -fbounds-check | |
OBJS = ./mod_is_even.o ./mod_test.o ./main.o | |
main.exe: $(OBJS) | |
gfortran $(FCFLAGS) -o ./main.exe $(OBJS) | |
%.o: %.f08 | |
gfortran $(FCFLAGS) -c $< | |
clean: | |
rm ./*.mod ./*.o |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module mod_is_even | |
! <module>s to import | |
use, intrinsic :: iso_fortran_env | |
! require all variables to be explicitly declared | |
implicit none | |
! accessibility of the <subroutine>s and <function>s in this <module> | |
public :: is_even_bit | |
public :: is_even_mod | |
! contained <subroutine>s and <function>s are below | |
contains | |
pure function is_even_bit (i) result(is_even) | |
! argument(s) for this <function> | |
integer(INT32), intent(in) :: i | |
! return value of this <function> | |
logical :: is_even | |
is_even = .not. btest(i= i, pos= 0) | |
end function is_even_bit | |
pure function is_even_mod (i) result(is_even) | |
! argument(s) for this <function> | |
integer(INT32), intent(in) :: i | |
! return value of this <function> | |
logical :: is_even | |
is_even = (mod(a= i, p= 2_INT32) .eq. 0_INT32) | |
end function is_even_mod | |
end module mod_is_even |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module mod_test | |
! <module>s to import | |
use, intrinsic :: iso_fortran_env | |
! require all variables to be explicitly declared | |
implicit none | |
! accessibility of the <subroutine>s and <function>s in this <module> | |
public :: generate_sample | |
public :: test_method | |
private :: random_number_int | |
! constant(s) for this <module> | |
integer(INT32), parameter, private :: num_sample_min = 0_INT32 | |
integer(INT32), parameter, private :: num_trial_min = 0_INT32 | |
integer(INT32), parameter, private :: stat_allocate_success = 0_INT32 | |
! contained <subroutine>s and <function>s are below | |
contains | |
! | |
! [reference] | |
! - http://fortranwiki.org/fortran/show/random_number | |
! | |
pure function random_number_int (source, first, last) result(harvest) | |
! argument(s) for this <function> | |
real(REAL64) , intent(in) :: source ! random sample from intrinsic subroutine <RANDOM_NUMBER> | |
integer(INT32) , intent(in) :: first ! lowest integer in range of integers to get | |
integer(INT32) , intent(in) :: last ! highest integer in range of integers to get | |
! return value of this <function> | |
integer(INT32) :: harvest | |
harvest = first + floor( (last - first + 1_INT32) * source ) | |
end function random_number_int | |
subroutine generate_sample (num_sample, sample, first, last) | |
! argument(s) for this <subroutine> | |
integer(INT32) , intent(in) :: num_sample ! number of samples to generate | |
integer(INT32) , intent(inout) , allocatable :: sample(:) ! array to store the generated samples | |
integer(INT32) , intent(in) :: first ! lowest integer in range of integers to get | |
integer(INT32) , intent(in) :: last ! highest integer in range of integers to get | |
! variable(s) for this <subroutine> | |
integer :: buffer_stat | |
real(REAL64) :: buffer_rand | |
integer(INT32) :: iter | |
! STEP.01 | |
! check the given arguments | |
if ( num_sample .le. num_sample_min ) then | |
write(unit= ERROR_UNIT, fmt='(A)') 'The number of samples must be greater than zero.' | |
stop | |
end if | |
if (first .ge. last) then | |
write(unit= ERROR_UNIT, fmt='(A)') 'The range of integers to get is invalid.' | |
stop | |
end if | |
! STEP.02 | |
! allocate the array to store the generated samples | |
allocate( sample(num_sample) , stat= buffer_stat ) | |
select case (buffer_stat) | |
case(stat_allocate_success) | |
! Nothing to do in this block | |
case default | |
write(unit= ERROR_UNIT, fmt='(A)') 'Falied to allocate an array to store the generated samples.' | |
write(unit= ERROR_UNIT, fmt='(A,1X,I0)') 'Error Code >', buffer_stat | |
stop | |
end select | |
! STEP.03 | |
! generate & store the samples for the test | |
do iter = 1_INT32 , num_sample , 1_INT32 | |
call random_number(buffer_rand) | |
sample(iter) = random_number_int(source = buffer_rand, first= first, last= last) | |
end do | |
! STEP.END | |
return | |
end subroutine generate_sample | |
subroutine test_method (is_even, sample, num_trial) | |
! argument(s) for this <function> | |
interface | |
pure function is_even (i) | |
! <module>s to import | |
use, intrinsic :: iso_fortran_env | |
! argument(s) for this <function> | |
integer(INT32), intent(in) :: i | |
! return value of this <function> | |
logical :: is_even | |
end function is_even | |
end interface | |
integer(INT32), intent(in) :: sample(:) ! samples to test the method | |
integer(INT32), intent(in) :: num_trial ! number of trials | |
! variable(s) for this <subroutine> | |
logical :: buffer_stat | |
integer(INT32) :: iter_sample | |
integer(INT32) :: iter_trial | |
integer(INT64) :: clock_count_end | |
integer(INT64) :: clock_count_max | |
integer(INT64) :: clock_count_rate | |
integer(INT64) :: clock_count_start | |
! STEP.01 | |
! check the given arguments | |
if ( num_trial .le. num_trial_min ) then | |
write(unit= ERROR_UNIT, fmt='(A)') 'The number of trials must be greater than zero.' | |
stop | |
end if | |
! STEP.02 | |
! record the <SYSTEM_CLOCK> before starting the target process | |
call system_clock(count= clock_count_start, count_rate= clock_count_rate, count_max= clock_count_max) | |
! STEP.03 | |
! execute the target process | |
do iter_trial = 1_INT32 , num_trial , 1_INT32 | |
do iter_sample = 1_INT32 , size(sample) , 1_INT32 | |
buffer_stat = is_even( sample(iter_sample) ) | |
end do | |
end do | |
! STEP.04 | |
! record the cpu time after the target process | |
call system_clock(count= clock_count_end) | |
! STEP.05 | |
! show the result | |
write( unit= OUTPUT_UNIT, fmt='("system clock >",1X,I20)' ) clock_count_end - clock_count_start | |
! STEP.END | |
return | |
end subroutine test_method | |
end module mod_test |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment