- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Even simple uses of SELECT CASE appear to be slow. Using "ifx -O3" or "ifort -O3" on a simple Linux setup I get very different times for the different inner operations that with three other compilers all reduce to the same time or have the SELECT CASE the fastest. Is there an additional
option required to optimize SELECT CASE?
The example is rather unnatural to prevent the loops from being eliminated and to compare the simple code differences in the inner code "DO I=1,SZ" loops, but it simple repeatedly converts an ASCII string to uppercase just as a sample, as it shows that SELECT CASE with CHARACTER cases seem to be particularly slow. I have tried a variety of options in addition to -O and so far some of these are horribly slow.
program main
implicit none
integer, parameter :: ade_a = iachar('a'), ade_z = iachar('z'), diff = iachar('A') - iachar('a')
character(len=*), parameter :: in = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789?/,./!@#$%^&'
integer, parameter :: sz = len(in), calls = 1000000
character(len=sz) :: string, str, keep
integer :: i, j, k, ch, ii
real :: rr
doubleprecision :: time_start, time_finish
do k=0,3
call setup() ! get a baseline time with a basic assign, assuming loop not optimized away
do j = 1, calls
select case(k)
case(0)
! just an assign for a baseline, assuming loop is not optimized away
string = str
case(1)
do i=1,sz
ch = iachar(str(i:i))
if (ch >= ade_a .and. ch <= ade_z) ch = ch + diff
string(i:i) = achar(ch)
enddo
case(2)
do i=1,sz
select case (str(i:i))
case ('a':'z'); string(i:i) = achar(iachar(str(i:i)) + diff)
case default; string(i:i) = str(i:i)
end select
enddo
case(3)
do i=1,sz
ch = iachar(str(i:i))
select case (ch)
case (ade_a:ade_z); string(i:i) = achar(ch + diff)
case default; string(i:i) = str(i:i)
end select
enddo
case default
stop '<ERROR>'
end select
if (j .eq. ii) keep = string
end do
call finish()
end do
contains
subroutine setup()
real :: rr
str = random_string(in, len(in)) ! do some random stuff to keep loops from being optimzed away
call random_number(rr)
ii = max(1, int(rr*calls))
keep = ''
call cpu_time(time_start)
end subroutine setup
subroutine finish()
call cpu_time(time_finish)
print '(i10,1x,*(g0,1x))', int(100000*(time_finish - time_start)), ' ', keep, (time_finish - time_start)
end subroutine finish
function random_string(chars, length) result(out)
character(len=*), intent(in) :: chars
integer, intent(in) :: length
character(len=:), allocatable :: out
real :: x
integer :: ilen, which, i
ilen = len(chars)
out = ''
if (ilen .gt. 0) then
do i = 1, length
call random_number(x)
which = nint(real(ilen - 1)*x) + 1
out = out//chars(which:which)
end do
end if
end function random_string
end program main
655 acAX$9y!69z,h.Z2we/hdgP@g!hV?j&5bm&3qWNJ9c^R4G06Gp1X1pxt3OUUKIjNo%RbxOXbtI .6553999999999999E-02
2254 RUDM7Y.Z2TXW@%LFXSM@NNPBKOSVJ3W%.5%VWRV#QXOTN?/HSUOH0TWCL/$OXP$S2!A%4QNU7L .2254600000000000E-01
184174 WC8O^@7EPUIMMPUFB7O#1N5DSTAQ!P$/ZRC/CO1/YL9T6E2S#P.JZ,VLTPX,PKTYS?XMZTE6DO 1.841741000000000
2861 4P4NHP3VPUY4FFY%7MPG.6@DRIWEQ,.ZWMQIURVAP4XAF%F2ZF9EE/WJD#ES2%RBW$JEP.E?YZ .2861899999999995E-01
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No there is no option to help with SELECT CASE. if the data was not random you could try PGO with -prof-gen and -prof-use. but with random data this won't help. Select case will not vectorize.
Character intrinsics are not vectorized and are not particularly speedy. CASE statements do not create masked vector operations available in AVX2 and above. Branchy code, lots of intrinsics calls for character functions. Not much the compiler can do here.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page