# Time difference using if and where statement

**URL:** <https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210>\
**Category:** Help\
**Created:** [April 11, 2022, 9:17pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210 "2022-04-11T21:17:30Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shahid](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/shahid/32/3672_2.png) [@Shahid](https://fortran-lang.discourse.group/u/Shahid)\
**Post date:** [April 11, 2022, 9:17pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/1 "2022-04-11T21:17:30Z")

</div>

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
```

---

<div class="post-metadata">

**Author:** ![Shahid](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/shahid/32/3672_2.png) [@Shahid](https://fortran-lang.discourse.group/u/Shahid)\
**Post date:** [April 11, 2022, 9:54pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/3 "2022-04-11T21:54:47Z")

</div>

I am using gfortran on virtual machine. with compiler options: gfortran main.f90 -o main

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 11, 2022, 9:54pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/4 "2022-04-11T21:54:55Z")

</div>

`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

---

<div class="post-metadata">

**Author:** ![Shahid](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/shahid/32/3672_2.png) [@Shahid](https://fortran-lang.discourse.group/u/Shahid)\
**Post date:** [April 11, 2022, 10:03pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/5 "2022-04-11T22:03:55Z")

</div>

If both statements are equivalent then why where statement takes a longer execution time?

---

<div class="post-metadata">

**Author:** ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)\
**Post date:** [April 11, 2022, 10:12pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/7 "2022-04-11T22:12:30Z")

</div>

They are not. As @kargl noted, `where` should be outside the loops. Otherwise you make the loop over c array quadruple.

---

<div class="post-metadata">

**Author:** ![mecej4](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mecej4/32/855_2.png) [@mecej4](https://fortran-lang.discourse.group/u/mecej4)\
**Post date:** [April 11, 2022, 11:06pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/9 "2022-04-11T23:06:31Z")

</div>

> [@Shahid](#):
>
> `c = 0.01+0.8*r`

If I read your intent correctly, and since you seem to regard speed as important, consider replacing

```auto
c = 0.01+0.8*r

```

by

```auto
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.

---

<div class="post-metadata">

**Author:** ![FortranFan](https://avatars.discourse-cdn.com/v4/letter/f/96bed5/32.png) [@FortranFan](https://fortran-lang.discourse.group/u/FortranFan)\
**Post date:** [April 11, 2022, 11:25pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/10 "2022-04-11T23:25:08Z")

</div>

> [@mecej4](#):
>
> replacing
> 
> ```auto
> c = 0.01+0.8*r
> 
> ```
> 
> by
> 
> ```auto
> c = 0.0002+(0.8-0.0002)*r
> 
> ```

It’s highly doubtful OP is interested in a lesson in arithmetic! +1 for clever programming though!

@shahid,

If you’re really need to do such comparisons, then as indicated upthread, do

```fortran
   where (c>=0.80) c=0.80
   where (c<0.0002) c=0.0002

```

against your `IF` inside your DO loop.

That is, place the `WHERE` statements outside your loop.

Also, try not to include IO statements inside of your timing measurements, your `PRINT` can introduce sufficient noise to affect your timing.

---

<div class="post-metadata">

**Author:** ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)\
**Post date:** [April 11, 2022, 11:30pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/11 "2022-04-11T23:30:52Z")

</div>

Since MIN and MAX are elemental functions, I think the code can be written

```auto
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

```

---

<div class="post-metadata">

**Author:** ![Shahid](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/shahid/32/3672_2.png) [@Shahid](https://fortran-lang.discourse.group/u/Shahid)\
**Post date:** [April 11, 2022, 11:59pm UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/12 "2022-04-11T23:59:05Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Shahid](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/shahid/32/3672_2.png) [@Shahid](https://fortran-lang.discourse.group/u/Shahid)\
**Post date:** [April 12, 2022, 12:03am UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/13 "2022-04-12T00:03:56Z")

</div>

I ran with the -O2 flag without changing anything in the code and it shows faster time. So it confuses me why it is not the solution?

---

<div class="post-metadata">

**Author:** ![mecej4](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/mecej4/32/855_2.png) [@mecej4](https://fortran-lang.discourse.group/u/mecej4)\
**Post date:** [April 12, 2022, 12:06am UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/14 "2022-04-12T00:06:19Z")

</div>

You seem not to realize an important point. You execute the WHERE construct N^2 = 4096 times, even though doing just one execution was enough!

---

<div class="post-metadata">

**Author:** ![zaikunzhang](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/zaikunzhang/32/785_2.png) [@zaikunzhang](https://fortran-lang.discourse.group/u/zaikunzhang)\
**Post date:** [April 9, 2024, 3:47am UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/16 "2024-04-09T03:47:01Z")

</div>

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.

```fortran
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

```

---

<div class="post-metadata">

**Author:** ![Shahid](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/shahid/32/3672_2.png) [@Shahid](https://fortran-lang.discourse.group/u/Shahid)\
**Post date:** [April 9, 2024, 4:20am UTC](https://fortran-lang.discourse.group/t/time-difference-using-if-and-where-statement/3210/17 "2024-04-09T04:20:51Z")

</div>

Yeah. That is correct.
