Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Need efficient Fortran equivalent to Matlab accumarray

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: Ed Stein8778

Date: 15 May, 2010 08:09:23

Message: 1 of 7

Hello,

I'm looking for a efficient, vectorized Fortran90/95 code that works like
Matlab's accumarray function, which accumulates elements of an input
(data) array, based on subscript arrays (of the same shape as the data
array) which point to the location in a new target array that the input
array are to accumulate into. More precisely:

Given a data matrix A sized (M,N), and a set of row indexes DROW(M,N) and
column indexes DCOLUMN(M,N), the accumarray function accumulates data
from A into a new array D sized (Md,Nd) where D(md,nd) is the sum of
A(m,n) for all values of m,n for which DROW(m,n)=md and DCOLUMN(m,n)=nd.

Matlab's accumarray does this:
  
   D = accumarray([DROW(:) DCOLUMN(:)], A(:) );

Can anyone suggest some Fortran code equivalent that avoids loops?
Though Matlab's accumarray handles arbitrary rank, restricting the
Fortran version to 2-d arrays A and D as in the above example is fine.

Thanks very much,
Ed

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: dpb

Date: 15 May, 2010 09:15:10

Message: 2 of 7

Ed Stein8778 wrote:
> Hello,
>
> I'm looking for a efficient, vectorized Fortran90/95 code that works like
> Matlab's accumarray function, which accumulates elements of an input
> (data) array, based on subscript arrays (of the same shape as the data
> array) which point to the location in a new target array that the input
> array are to accumulate into. More precisely:
>
> Given a data matrix A sized (M,N), and a set of row indexes DROW(M,N) and
> column indexes DCOLUMN(M,N), the accumarray function accumulates data
> from A into a new array D sized (Md,Nd) where D(md,nd) is the sum of
> A(m,n) for all values of m,n for which DROW(m,n)=md and DCOLUMN(m,n)=nd.
>
> Matlab's accumarray does this:
>
> D = accumarray([DROW(:) DCOLUMN(:)], A(:) );
>
> Can anyone suggest some Fortran code equivalent that avoids loops?
> Though Matlab's accumarray handles arbitrary rank, restricting the
> Fortran version to 2-d arrays A and D as in the above example is fine.

As in Matlab, vectorization in source code isn't necessarily always the
answer.

Just as you build blocks in Matlab in m-files that sometimes have loops,
here I think the solution is to write a routine and hide the details,
then call it.

--

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: John D'Errico

Date: 15 May, 2010 12:58:06

Message: 3 of 7

dpb <none@non.net> wrote in message <hsloqb$d75$1@news.eternal-september.org>...
> Ed Stein8778 wrote:
> > Hello,
> >
> > I'm looking for a efficient, vectorized Fortran90/95 code that works like
> > Matlab's accumarray function, which accumulates elements of an input
> > (data) array, based on subscript arrays (of the same shape as the data
> > array) which point to the location in a new target array that the input
> > array are to accumulate into. More precisely:
> >
> > Given a data matrix A sized (M,N), and a set of row indexes DROW(M,N) and
> > column indexes DCOLUMN(M,N), the accumarray function accumulates data
> > from A into a new array D sized (Md,Nd) where D(md,nd) is the sum of
> > A(m,n) for all values of m,n for which DROW(m,n)=md and DCOLUMN(m,n)=nd.
> >
> > Matlab's accumarray does this:
> >
> > D = accumarray([DROW(:) DCOLUMN(:)], A(:) );
> >
> > Can anyone suggest some Fortran code equivalent that avoids loops?
> > Though Matlab's accumarray handles arbitrary rank, restricting the
> > Fortran version to 2-d arrays A and D as in the above example is fine.
>
> As in Matlab, vectorization in source code isn't necessarily always the
> answer.
>
> Just as you build blocks in Matlab in m-files that sometimes have loops,
> here I think the solution is to write a routine and hide the details,
> then call it.
>
> --

Exactly. In Fortran, a loop will be nicely efficient.
So write a routine that does it, and then you have it.

John

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: dpb

Date: 15 May, 2010 13:23:18

Message: 4 of 7

John D'Errico wrote:
> dpb <none@non.net> wrote in message
> <hsloqb$d75$1@news.eternal-september.org>...
>> Ed Stein8778 wrote:
>> > Hello,
>> > > I'm looking for a efficient, vectorized Fortran90/95 code that
>> works like > Matlab's accumarray ...
...
>> > > Can anyone suggest some Fortran code equivalent that avoids
>> loops?...
>>
>> As in Matlab, vectorization in source code isn't necessarily always
>> the answer.
>>
>> Just as you build blocks in Matlab in m-files that sometimes have
>> loops, here I think the solution is to write a routine and hide the
>> details, then call it.
>>
>> --
>
> Exactly. In Fortran, a loop will be nicely efficient.
> So write a routine that does it, and then you have it.

I'd note for OP that even if were to find a way to use Fortran array
syntax w/ slice notation or somesuch in all likelihood the result would
be slower than straightforward loops owing to intermediate temporaries
and such. This is often a complaint in the comp.lang.fortran group when
folks try somesuch.

I'll also note that while he can create a functional form that uses a
pointer as a return, F95+TR doesn't have dynamic allocation on
assignment so the posited syntax of a function call such as Matlab alone
is not possible. That would require as a minimum a compiler that
implements F2003, not F95 (and I'm not absolutely sure that the FUNCTION
can return the array itself there, even, either and don't have the
inclination to go look it up at the moment :) ).

Consequently, I'd recommend writing it as a SUBROUTINE rather than a
FUNCTION where the ALLOCATABLE array allocation can be handled in an
assumed-length argument.

For efficiency, make sure that summations are performed as far as
possible in column major order, of course, consistent w/ the subindexing
requested for any given call.

--

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: dpb

Date: 15 May, 2010 15:33:40

Message: 5 of 7

dpb wrote:
...

> Consequently, I'd recommend writing it as a SUBROUTINE rather than a
> FUNCTION where the ALLOCATABLE array allocation can be handled in an
> assumed-length argument.
...

Dang, I mixed metaphors...an ALLOCATABLE array is an ALLOCATABLE array,
assumed-length is something else. I thought I had edited this to fix
the slipup, sorry.

The problem one could get into doing what OP wants is that if the
ALLOCATE statement is in the accumarray() routine, it is then the
responsibility of the caller to DEALLOCATE it at the appropriate
time/place. Fortran's dynamic memory particularly at F95 isn't so
flexible as Matlab; there are more features incorporated in F2003.

--

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: James Tursa

Date: 15 May, 2010 19:05:08

Message: 6 of 7

dpb <none@non.net> wrote in message <hsm7bn$lu5$1@news.eternal-september.org>...
>
> I'd note for OP that even if were to find a way to use Fortran array
> syntax w/ slice notation or somesuch in all likelihood the result would
> be slower than straightforward loops owing to intermediate temporaries
> and such. This is often a complaint in the comp.lang.fortran group when
> folks try somesuch.
>
> I'll also note that while he can create a functional form that uses a
> pointer as a return, F95+TR doesn't have dynamic allocation on
> assignment so the posited syntax of a function call such as Matlab alone
> is not possible. That would require as a minimum a compiler that
> implements F2003, not F95 (and I'm not absolutely sure that the FUNCTION
> can return the array itself there, even, either and don't have the
> inclination to go look it up at the moment :) ).

To complete the thought, yes it can. e.g., you can have a function return a dynamically sized array that is based on the size of the inputs. The main problem with the approach, IMO, is that for many (most?) implementations the memory for the array comes off the stack and not off the heap. So if you are working with large arrays you can easily blow your stack and bomb the program. Also, if the result is assigned to a variable by the calling routine there is an extra data copy involved.

> Consequently, I'd recommend writing it as a SUBROUTINE rather than a
> FUNCTION where the ALLOCATABLE array allocation can be handled in an
> assumed-length argument.

That is the most efficient approach for the above stated reasons. The allocated memory comes off the heap instead of the stack, and you avoid the extra memory copy.

What I sometimes do is create both versions and have a generic routine interface set up so that you can call it either way.

James Tursa

Subject: Need efficient Fortran equivalent to Matlab accumarray

From: dpb

Date: 15 May, 2010 19:50:57

Message: 7 of 7

James Tursa wrote:
> dpb <none@non.net> wrote in message
> <hsm7bn$lu5$1@news.eternal-september.org>...
...

>> I'll also note that while he can create a functional form that uses a
>> pointer as a return, F95+TR doesn't have dynamic allocation on
>> assignment so the posited syntax of a function call such as Matlab
>> alone is not possible. That would require as a minimum a compiler
>> that implements F2003, not F95 (and I'm not absolutely sure that the
>> FUNCTION can return the array itself there, even, either and don't
>> have the inclination to go look it up at the moment :) ).
>
> To complete the thought, yes it can. e.g., you can have a function
> return a dynamically sized array that is based on the size of the
> inputs. ...

OK, James, thanks for the addendum.

For my own clarification -- that does require later than F95, correct?

The following compiles w/o warning but aborts in CVF6.6 on accessing any
element of x() and an ALLOCATED(x) returns false since AIUI F95 doesn't
know how to assign to the variable x anything other than as a REAL
variable, not the elements of array x(:).

program foobar
   real, allocatable :: x(:)
   x = foo(10)

   ! Dies on bounds error cuz can't recognize and assign to an array...
   ! This is F95 limitation, not compiler flaw, correct?
   write(*,*) x(1)
end

function foo(n) result(x)
   integer :: n
   real, allocatable :: x(:)

   allocate(x(n))

   x = 3.0
end function


OTOH, a SUBROUTINE form works ok, w/ the previous difficulty of
requiring to keep track of where/when the array is DEALLOCATEd


--

Tags for this Thread

No tags are associated with this thread.

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us