Array Operations in Fortran

code

#define OPER +
program main
    implicit none
    real(kind=8), dimension(:), allocatable :: matx1
    real(kind=8), dimension(:), allocatable :: maty1
    real(kind=8), dimension(:), allocatable :: matz1
    real(8)::spenttime
    integer::i,j
    integer,parameter::n=40000000
    integer(kind=8)::time1,time2,time_rate

    allocate (matx1(n))
    allocate (maty1(n))
    allocate (matz1(n))
    call random_number(matx1)
    call random_number(maty1)

    call system_clock(time1,time_rate)
    matz1 = matx1 OPER maty1
    call system_clock(time2,time_rate)
    spenttime=(time2-time1)/real(time_rate,8)
    write (*,*) "spenttime:",spenttime;
    write (*,*) "print    :",matz1(1);

    call system_clock(time1,time_rate)
    do i=1,n
        matz1(i) = matx1(i) OPER maty1(i)
    end do
    call system_clock(time2,time_rate)
    spenttime=(time2-time1)/real(time_rate,8)
    write (*,*) "spenttime:",spenttime;
    write (*,*) "print    :",matz1(1);

    call system_clock(time1,time_rate)
    matz1= add(matx1, maty1)
    call system_clock(time2,time_rate)
    spenttime=(time2-time1)/real(time_rate,8)
    write (*,*) "spenttime:",spenttime;
    write (*,*) "print    :",matz1(1);

    deallocate (matx1)
    deallocate (maty1)
    deallocate (matz1)
contains
    elemental function add(a,b)result(c)
        real(kind=8), intent(in) :: a,b
        real(kind=8):: c
        c=a OPER b
    end function add
end program main

result

> gfortran
spenttime:  0.17802660000000001
print    :  0.96720229161006710
spenttime:   4.8475799999999999E-002
print    :  0.96720229161006710
spenttime:   4.7800099999999998E-002
print    :  0.96720229161006710
> ifort
 spenttime:  6.500000000000000E-002
 print    :  0.492660442309517
 spenttime:  3.700000000000000E-002
 print    :  0.492660442309517
 spenttime:  3.600000000000000E-002
 print    :  0.492660442309517
> nvfortran
 spenttime:   0.1808910000000000
 print    :    1.064990525239708
 spenttime:   4.8655100000000000E-002
 print    :    1.064990525239708
 spenttime:   6.2480000000000001E-002
 print    :    1.064990525239708

flags

ifort.exe 3.f90 -O3 -Qxcore-avx2 -fpp 
nvfortran 3.f90 -O3 -mavx2 -cpp 
gfortran  3.f90 -O3 -march=native -mavx2 -cpp 

it is shown that array OPER array is slower than do loop. OPER ={+,-,*,/,**}, Is there some problems in my code?

2 Likes

Try to reorder your calculation, the first one will probably always be the slowest.

To avoid this, you should repeat your micro-benchmark a couple of times by adding a loop or similar to remove any artifacts you get in the first couple of runs.

4 Likes

Yes , you are right, when copy the first calculation twice, it is shown different time spent. And the first one is slowest. :grinning:

Or insert matz1 = 0 right after the statement call random_number(maty1)

1 Like

Yes , It is useful , and time for first example is same as others. Thanks both of you.

1 Like