I am trying to understand the if and where statement with the following example. Apparently, there is no error in the code but there is a lot of difference in the output time. The where statement is quite slow. So far i have not found any reason for it. Does where statement execution always take more time?
program where_test
implicit none
integer :: tsteps,i,j
integer, parameter :: N = 64
real, dimension(N,N) :: r,c
real :: t_start, t_end
call cpu_time(t_start)
do tsteps = 1, 100000
call random_number(r)
c = 0.01+0.8*r
do i = 1, N
do j= 1, N
! if (c(i,j)>=0.80) c(i,j)=0.80
! if (c(i,j)<0.0002) c(i,j)=0.0002
where (c>=0.80) c=0.80
where (c<0.0002) c=0.0002
end do
end do
if(mod(tsteps,1000).eq.0) print*, 'Done steps = ',tsteps
end do
call cpu_time(t_end)
print*, 'Time = ', t_end - t_start
end program
where (c>=0.8)... operates on the whole array, element by element, so it is by itself equivalent of an if(c(i, j) >= 0.8)... enclosed in double do loop.
Also, the second if/where is a no-op as c=0.01+0.8*r cannot be less than 0.002
If I read your intent correctly, and since you seem to regard speed as important, consider replacing
c = 0.01+0.8*r
by
c = 0.0002+(0.8-0.0002)*r
and doing away with the DO loops on i and j. You will not need IF or WHERE constructs at all. Your original code throws away a small section of of the random numbers that were generated. The suggested change entails no such discarding.
Since MIN and MAX are elemental functions, I think the code can be written
program where_test
implicit none
integer :: tsteps
integer, parameter :: N = 64
real, dimension(N,N) :: c
real :: t_start, t_end
call cpu_time(t_start)
do tsteps = 1, 100000
call random_number(c)
c = max(0.002,min(0.8,0.01 + 0.8*c))
if (mod(tsteps,1000).eq.0) print*, 'Done steps = ',tsteps
end do
call cpu_time(t_end)
print*, 'Time = ', t_end - t_start
end program
My basic idea is just to understand the where construct or statement. In comparison to the if statement or if construct I saw that the where construct is taking a long time. So using -O2 compiler flag with gfortran the where construct shows faster execution (my original code at the top). Therefore it appears to me that where construct execution speed depends on the optimization flag.
As pointed out by others, the correct comparison should be as follows (I have not tried the code). Note that where is placed outside the loops.
program where_test
implicit none
integer :: tsteps,i,j
integer, parameter :: N = 64
real, dimension(N,N) :: r,c
real :: t_start, t_end
call cpu_time(t_start)
do tsteps = 1, 100000
call random_number(r)
c = 0.01+0.8*r
!do i = 1, N
! do j= 1, N
!
! if (c(i,j)>=0.80) c(i,j)=0.80
! if (c(i,j)<0.0002) c(i,j)=0.0002
!
! end do
!end do
where (c>=0.80) c=0.80
where (c<0.0002) c=0.0002
if(mod(tsteps,1000).eq.0) print*, 'Done steps = ',tsteps
end do
call cpu_time(t_end)
print*, 'Time = ', t_end - t_start
end program