Hello,
I just want to share with the list my "discovery" of a very nice memory
allocation profiling, tracing and error detection library called mpatrol:
http://www.cbmamiga.demon.co.uk/mpatrol/
I needed to do some work with the author to get it to work with LF95 on
Linux, but I like the tool a lot. Attached is a simple Fortran 90 test
program which I shared with you last week and which shows the
"syntactic-sugar" that Lahey used when implementing allocatable components.
The main function calls three functions, timing_pointer, timing_allocatables
and timing_arrays which perform array operations on two arrays that are
either pointers, allocatable arrays, or "plain" arrays.
The attached jpg image shows the allocation graph of the program (only large
allocations). It is clearly seen that the compiler allocates an array
temporary three times during the call to timing_pointer and
timing_allocatables, but not in the call to timing_arrays. One can view
details of the allocaitons as a file and keep track of memory leeks and
corrupt heaps and such with this library, and also trace total memory
allocation for a program as a function of time. In other words, a very
useful tool.
Best,
Aleksandar
_____________________________________________
Aleksandar Donev
http://www.pa.msu.edu/~donev/
[log in to unmask]
(517) 432-6770
Department of Physics and Astronomy
Michigan State University
East Lansing, MI 48824-1116
_____________________________________________
module type_module
implicit none
type, public :: allocatables
real, allocatable, dimension(:) :: x, y
end type allocatables
end module type_module
module timing
use type_module
use StopWatch
implicit none
integer :: n_reps
type(watchtype) :: timer
contains
subroutine time_derived(xy)
type(allocatables), intent(inout) :: xy
real :: dot
integer :: reps
call Create_Watch(timer, name="Allocatable components")
call Reset_Watch(timer)
xy%x=1.0
call Start_Watch(timer)
do reps=1, n_reps
xy%x=xy%y*xy%x
xy%y=xy%x+1.0
dot=DOT_PRODUCT(xy%x, xy%y)
xy%x=xy%x+dot*xy%y
end do
call Stop_Watch(timer)
call Print_Watch(timer)
call Destroy_Watch(timer)
end subroutine time_derived
subroutine time_pointers(x, y)
real, pointer, dimension(:) :: x, y
real :: dot
integer :: reps
call Create_Watch(timer, name="Pointer arrays")
call Reset_Watch(timer)
x=1.0
call Start_Watch(timer)
do reps=1, n_reps
x=y*x
y=x+1.0
dot=DOT_PRODUCT(x, y)
x=x+dot*y
end do
call Stop_Watch(timer)
call Print_Watch(timer)
call Destroy_Watch(timer)
end subroutine time_pointers
subroutine time_arrays(x, y)
real, dimension(:), intent(inout) :: x, y
real :: dot
integer :: reps
call Create_Watch(timer, name="Plain arrays")
call Reset_Watch(timer)
x=1.0
call Start_Watch(timer)
do reps=1, n_reps
x=y*x
y=x+1.0
dot=DOT_PRODUCT(x, y)
x=x+dot*y
end do
call Stop_Watch(timer)
call Print_Watch(timer)
call Destroy_Watch(timer)
end subroutine time_arrays
end module timing
program test
use type_module
use timing
implicit none
type(allocatables) :: xy
real, pointer, dimension(:) :: x, y
integer :: n
! write(*,*) "n, n_reps?"
! read(*,*) n, n_reps
n=1000000
n_reps=1
allocate(xy%x(n), xy%y(n))
allocate(x(n), y(n))
call time_derived(xy)
call time_pointers(x, y)
call time_arrays(xy%x, xy%y)
deallocate(xy%x, xy%y, x, y)
end program test
|