- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
In my codes there's a lot of "if..else" statements. I'm told that they tend to slow down codes.
So I'm thinking of other alternatives, like the one below:
The 1st subroutineif_elseuses the "if...else" statement but the 2nd if_else2 does some arithimetics to avoid that.
I tested the runtime but they are almost the same, both in debug and optimized mode. Does this mean it makes no difference whether "if..else" is used?
Thanks!
program if_else_test
!test whether if_else can be avoided
implicit none
integer,parameter :: loop_no=10000,size=10000,call_time=20000
integer :: i
real :: array(size)
do i=1,call_time
call if_else2(loop_no,size,array) !or call if_else(loop_no,size,array)
end do
contains
subroutine if_else(loop_no,size,array)
!use if...else
integer, intent(in) :: loop_no,size
integer :: w(size)
real :: u(size),v(size)
real, intent(inout) :: array(size)
do i=1,loop_no
call random_number(u(i)); call random_number(v(i))
w(i)=(u(i)-v(i))/abs(u(i)-v(i))
if (w(i)==1) then
array(i)=2.*u(i)
else if (w(i)==-1) then
array(i)=2.*v(i)
end if
end do
end subroutine if_else
subroutine if_else2(loop_no,size,array)
!use alternative
integer, intent(in) :: loop_no,size
integer :: w(size)
real :: u(size),v(size)
real, intent(inout) :: array(size)
do i=1,loop_no
call random_number(u(i)); call random_number(v(i))
w(i)=(u(i)-v(i))/abs(u(i)-v(i))
array(i)= (w(i)+1)*u(i) - (w(i)-1)*v(i)
end do
end subroutine if_else2
end program if_else_test
Link Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would suggest something like this (untested):
I think this is easier to understand and does not suffer from potential floating point rounding errors as the original code does (there is no guarantee w(i) will be exactly equal to 1 or -1, and abs(u(i)-v(i)) could be zero).
However, I would not expect a large difference in speed. The biggest impact could, I guess, be achieved by using a different random number generator that is adapted to your problem (fast, but still "random" enough).
[fortran]subroutine if_else(loop_no, size, array) integer, intent(in) :: loop_no, size real, intent(out) :: array(size) integer :: i real :: u, v do i = 1, loop_no call random_number(u) call random_number(v) array(i) = 2*max(u, v) end do end subroutine if_else [/fortran]
I think this is easier to understand and does not suffer from potential floating point rounding errors as the original code does (there is no guarantee w(i) will be exactly equal to 1 or -1, and abs(u(i)-v(i)) could be zero).
However, I would not expect a large difference in speed. The biggest impact could, I guess, be achieved by using a different random number generator that is adapted to your problem (fast, but still "random" enough).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Performance impact of if..else is more significant when it affects auto-vectorization. As you call a serial random number generator, the impact of the if..else would be relatively small here.
As the preceding response hinted, a selection by max() (or by an if which the compiler recognizes as equivalent) would be vectorizable in the absense of the subroutine call.
As the preceding response hinted, a selection by max() (or by an if which the compiler recognizes as equivalent) would be vectorizable in the absense of the subroutine call.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Tom_p and TimP!
Well, I'm actually giving an example. In my e.g., I am trying to use :
array(i) = (w(i)+1)*u(i) - (w(i)-1)*v(i)
instead of
if (w(i)==1) then
array(i)=2.*u(i)
else if (w(i)==-1) then
array(i)=2.*v(i)
end if
The 1st case uses more operations but it avoids the use of "if..else".
Hence I wonder if the 1st case is better? Especially when optimizations are enabled.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Don't forget that RANDOM_NUMBER can take an array argument to get many at once.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page