Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Speed up array of derived type

Status
Not open for further replies.

euteam

Programmer
Jun 27, 2014
2
IT
Is it possible speed up a code like this (array of derived type)?

Code:
program test
  USE dati_m
  type(dato), target,allocatable :: dat(:)
  integer, pointer :: ip(:)
  real tbegin, tend
  allocate(dat(65000))
  ip => dat%i1
  call cpu_time(tbegin)
  do j=1,5000
      call set(ip,j)
  end do
  call cpu_time(tend)
  write(*,*) ' Time=',(tend-tbegin)
end program
module dati_m
  type :: dato
    real              :: r1 = 2
    integer           :: i1 = 33
    character(len=32) ::c1
    character(len=62) ::c2
  end type dato
  contains 
    subroutine set(p,i)
        integer, pointer :: p(:)
        integer ::i
        p(i)=p(i)+1
    end  subroutine set
end module dati_m

Thanks all
 
First of all, what exactly are you trying to achieve? I run your code and nothing much is happening, the value of 33 goes to 34 and stays there.

The following code actually increases the value and takes less time. Notice how I changed the rank of the pointer and set it to the integer of the i-th item of the dat array...as opposed to what you had without parenthesis...

Code:
program test
  USE dati_m
  type(dato), target,allocatable :: dat(:)
  integer, pointer :: ip
  real tbegin, tend
  allocate(dat(65000))
  ip => dat(1)%i1
  call cpu_time(tbegin)
  do j=1,5000
      call set(ip,j)
  end do
  call cpu_time(tend)
  write(*,*) ' Time=',(tend-tbegin)
end program
module dati_m
  type :: dato
    real              :: r1 = 2
    integer           :: i1 = 33
    character(len=32) ::c1
    character(len=62) ::c2
  end type dato  
  contains 
    subroutine set(p,i)
        integer, pointer :: p
        integer ::i
        p=p+1
    end  subroutine set
end module dati_m

 
So, are you trying on taking the integer of one of the array entries and increasing it by one? or, are you trying to increase every integer from every array entry by one? or are you just seeing what you can do? or you don't know what you are doing? [tongue]
 
I think your code should read
Code:
  call cpu_time(tbegin)
  do j=1,5000
      ip => dat(j)%i1
      call set(ip,j)
  end do
  call cpu_time(tend)

otherwise you might as well code it as
Code:
   dat(1)%i1 = dat(1)%i1 + 5000

and forget about the loop. Also, there is no guarantee that all the fields in dat will be zero after allocation. Are you looking for ways of speeding up the code without using features like OMP.

You could speed it up by not passing in j - that is one stack operation less.
 
Sorry - just saw the initialization: ignore comment about all the fields being zero.
 
Thanks all.

This test code is a little try. I need to refactor an old and complex code (about 800000 lines), I wish to use module with inside array of structure instead of old common of arrays (array of fields).

Old code has, inside nested do cycles, several call to subroutine like:
call sub1(array1, array2)
In old code there are several hundred of different subroutine.

I wish replace array1 of old code with dat%field1 in automatic by a script in this way: call sub1(dat%field1, dat%field2)

The syntax call sub1(dat%field1, dat%field2) is very slow respect old call sub1(array1,array2), because dat%field1 is an array of not contiguous elements and each call fortran make a copy in a temporary array for input and another in output.
I look for a way to speed up call with array of a field of structure (in this test code I try tu use pointer).


salgerman: your is code isn't the same as mine: try to put some write of dat(i)%I1 before program end

xwb: your code give the same resutls as mine, but I'cannot apply it in all call of old code, I need work with array and these arrays are records of a field (not always I have index J expòlicit, for example one subroutine look for a string id into an array id)
 
How about doing it the other way round
Code:
module dati_m
  type :: dato
    real              :: r1 = 2
    integer,pointer   :: ip ! this is now a pointer
    character(len=32) ::c1
    character(len=62) ::c2
  end type dato
contains
  subroutine set(p,i)
        integer:: p
        integer ::i
        p=p+1
    end  subroutine set
end module dati_m
program test
  USE dati_m
  type(dato), allocatable :: dat(:)
  integer, target, allocatable:: values(:)
  integer, parameter:: MAX = 65000
  real tbegin, tend
  allocate(dat(MAX))
  allocate(values(MAX))

  ! Initialize
  values = 33
  do j = 1, MAX
     dat(j)%ip = values(j)
  enddo

  ! when you want fast computations use values
  call cpu_time(tbegin)
  do j=1,MAX
      call set(values(j),j)
  end do
  call cpu_time(tend)
  write(*,*) ' Time=',(tend-tbegin)

  ! when time is not important use the type
  call cpu_time(tbegin)
  do j=1,MAX
      call set(datao(j)%ip,j)
  end do
  call cpu_time(tend)
  write(*,*) ' Time=',(tend-tbegin)
end program
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top