From b6dfa49c1a45ab2ff1da8dfa8f22a6f0ef17fa27 Mon Sep 17 00:00:00 2001 From: Marshall Ward Date: Tue, 1 Oct 2019 00:42:47 -0400 Subject: [PATCH] Use popcnt intrinsic for bitcount Profiling of the test suite showed a large amount of time (nearly 1/3) devoted to computing of bitcounts used as checksums for diagnostics. This patch replaces the bit loop with the popcnt intrinsic, which produces the same result and uses the hardware assembly instruction when available (e.g. popcnt in x86). This change appears to have reduced the runtime of the test suite from 4.5 minutes to under 3 minutes. --- src/framework/MOM_checksums.F90 | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/framework/MOM_checksums.F90 b/src/framework/MOM_checksums.F90 index c6a23667db..34390017ee 100644 --- a/src/framework/MOM_checksums.F90 +++ b/src/framework/MOM_checksums.F90 @@ -1849,20 +1849,12 @@ end subroutine chksum_error !> Does a bitcount of a number by first casting to an integer and then using BTEST !! to check bit by bit integer function bitcount(x) - real :: x !< Number to be bitcount + real, intent(in) :: x !< Number to be bitcount - ! Local variables - integer(kind(x)) :: y !< Store the integer representation of the memory used by x - integer :: bit - - bitcount = 0 - y = transfer(x,y) - - ! Fortran standard says that bit indexing start at 0 - do bit = 0, bit_size(y)-1 - if (BTEST(y,bit)) bitcount = bitcount+1 - enddo + integer, parameter :: xk = kind(x) !< Kind type of x + ! NOTE: Assumes that reals and integers of kind=xk are the same size + bitcount = popcnt(transfer(x, 1_xk)) end function bitcount end module MOM_checksums