Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Problem with ReAlloc

davidgraham
Beginner
1,475 Views
I am trying to use the routine ReAllocbut I get the following error.
What am I doing wrong?
subroutine TryReAlloc
real,allocatable::B(:)
integer::j
real::c
c=1.34
do j=1,10
call ReAlloc (B,j)
B(j)=c*j
end do
end subroutine TryReAlloc
!--------------------------
subroutine ReAlloc (A,n)
! A array
! n new size
real,allocatable::A(:)
integer::n,nOld
real,allocatable::Temp(:)
nOld=size(A)
if (nOld > n) RETURN
allocate (Temp(nOld))
Temp=A
Deallocate (A)
Allocate (A(n))
A(1:nOld)=Temp
end subroutine ReAlloc

Warning: In the call to REALLOC, actual argument #1 does not match the type and kind of the corresponding dummy argument.
call ReAlloc (B,j)
Thanks,
David
0 Kudos
6 Replies
Steven_L_Intel1
Employee
1,475 Views
You need an explicit interface to call a routine which has a deferred-shape (:) argument.
0 Kudos
davidgraham
Beginner
1,475 Views
Thanks, I have got it working now.
I am trying to repicate the Visual Basic redim preserve command.
I have found that the method of using the ReAlloc routine takes long time for a large array.
Repeating the loop 100 time takes 0.000 secs, 1,000 times takes 0.08 secs, 10,000 times takes 8.4 secs, 100,000 times - I gave up waiting.
Is there a more efficient way of doing this?
David
0 Kudos
Steven_L_Intel1
Employee
1,475 Views
Not at present. Fortran 2003 offers a way of doing a "realloc" on allocatables. You would have a bit better luck using POINTER as you could just move pointers around and just move the data once and not twice.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,475 Views

David,

You can speed it up using C code (or even, an equivalent Fortran code), by directly manipulating Fortran array descriptor. Basically, the F2000 MOVE_ALLOC does only one allocation instead of two, by means of having two pieces of allocated memory -- the old one and the new one -- simultaneously. Here's a sketch, which reusessome codefrom thread:

http://softwareforums.intel.com/ids/board/message?board.id=5&message.id=10361&view=by_date_ascending&page=1

Code:
void move_alloc(CVF_1D_DESCRIPTOR* A, int iSizeSingleElement,
  int iNewArraySize)
{
  void* lpOldAddress;
  lpOldAddress = A->lpAddress;
  A->lpAddress = malloc(iNewArraySize*iSizeSingleElement);

  // Copy the old contents into new location
  if (A->iAllocated) 
  {
     memcpy(lpOldAddress, A->lpAddress, A->Dim1.iExtent * iSizeSingleElement);
     // kill the old allocation
     free(lpOldAddress);
  }
  A->Dim1.iExtent = iNewArraySize;
  //Fill in the rest of A appropriately
}
Instead of malloc/memcpy/free you can use native Windows APIs or whatever. Note, however, that you have to use same allocators as were used to allocate the original array, meaning that you cannot e.g. free() memory which was not allocated with malloc() but e.g. with ALLOCATE (unless you happen to know which API is used by ALLOCATE internally). Thus, you should probably write your own (de)allocation routines in C, using the same malloc/free as used in move_alloc above.
Hope this helps,
Jugoslav
0 Kudos
Steven_L_Intel1
Employee
1,475 Views
Hey, Jugoslav's back!
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,475 Views
Alas, only temporarily :-( -- they merged some holidays so I got an extended weekend off. I'll be definitely back only in mid-August.
Regards
Jugoslav
0 Kudos
Reply