forums.silverfrost.com
Welcome to the Silverfrost forums

Author Message
johannes

Joined: 21 Jan 2011
Posts: 65
Location: Leimen, Germany

Posted: Fri Sep 26, 2014 9:30 am    Post subject: Bringing a slice of a rank 3 into a rank 2 array

Hi all,
could anyone give a clue how accelerate this primitive loop by means of advanced f90 capabilities?
 Code: k=...        FORALL (i=1:n,j=1:n)           b2(i,j)=b3(i,j,k)        end forall

Is it possible to use RESHAPE to map b3 to b2?
BR
johannes
LitusSaxonicum

Joined: 23 Aug 2005
Posts: 1797
Location: Yateley, Hants, UK

 Posted: Fri Sep 26, 2014 10:22 am    Post subject: Just a guess, Johannes, but couldn't you do something of the kind with EQUIVALENCE? I suppose it depends how big the maximum for k is before that gets tedious. (it would be handy if k=1). If n is small, you may get some benefit from loop unrolling, or if n is always a multiple of some other number by partial unrolling Eddie
johannes

Joined: 21 Jan 2011
Posts: 65
Location: Leimen, Germany

 Posted: Fri Sep 26, 2014 10:34 am    Post subject: Hi Eddie, even back in times of f70 I never touched EQUIVALENCE. Let my try later . IÄll come back johannes
johannes

Joined: 21 Jan 2011
Posts: 65
Location: Leimen, Germany

 Posted: Fri Sep 26, 2014 2:00 pm    Post subject: b2 and b3 arrays are allocatable. No EQUIVALENCE allowed. johannes
PaulLaidler

Joined: 21 Feb 2005
Posts: 5419
Location: Salford, UK

Posted: Fri Sep 26, 2014 5:05 pm    Post subject:

 Code: program main real b2(4,5), b3(4,5,3) do i = 1,4   do j = 1,5     do k = 1,3       b3(i,j,k)= 100*i+10*j+k     end do   end do end do      k = 2 b2(:,:)=b3(:,:,k) print*, b2(1,:) print*, b2(2,:) print*, b2(3,:) print*, b2(4,:) end
LitusSaxonicum

Joined: 23 Aug 2005
Posts: 1797
Location: Yateley, Hants, UK

 Posted: Fri Sep 26, 2014 8:47 pm    Post subject: Brilliant Paul! The three nested loops aren't part of the answer of course, but wouldn't it be better to have the i loop te innermost one? Eddie
PaulLaidler

Joined: 21 Feb 2005
Posts: 5419
Location: Salford, UK

 Posted: Sat Sep 27, 2014 7:17 am    Post subject: I don't know off hand. One could look at the /explist and also look to see if /opt makes any difference.
JohnCampbell

Joined: 16 Feb 2006
Posts: 1959
Location: Sydney

Posted: Tue Sep 30, 2014 1:44 am    Post subject:

Eddie,

The following change would certainly improve cache usage, especially when the array sizes increase.
 Code: do k = 1,3   do j = 1,5     do i = 1,4       b3(i,j,k)= 100*i+10*j+k     end do   end do end do

This becomes much more significant in the case of larger arrays, such as the equation solver SYMSOL where when the stiffness matrix is stored as ST(equations,band) will take much longer to run, compared to using the array ST(band,equations). The run time difference can be a factor of x10 to x100, which swamps any other attempt at coding efficiency. It occurs when the matrix is much larger than the processor cache size.

John
LitusSaxonicum

Joined: 23 Aug 2005
Posts: 1797
Location: Yateley, Hants, UK

 Posted: Tue Sep 30, 2014 7:06 am    Post subject: Hi John, I made it a question not an assertion so as not to offend anyone. This business of index order was something I first encountered in Kreitzberg and Schneiderman's book, c. early 1970s. I had little idea that it was so costly in time, but I had forgotten about cache misses, and was thinking only about how big the arrays can be. Paul's example probably doesn't count for much delay. Eddie
johannes

Joined: 21 Jan 2011
Posts: 65
Location: Leimen, Germany

 Posted: Mon Oct 06, 2014 3:22 pm    Post subject: Hi all, accessing every array element costs time. Isn't there any solution using pointers or so? Like: ptr=>b3(1,1,k) ! pinting to the first element in the slice and b2(1,1) = using the pointer ptr??? best regards johannes
PaulLaidler

Joined: 21 Feb 2005
Posts: 5419
Location: Salford, UK

Posted: Mon Oct 06, 2014 7:01 pm    Post subject:

The essence of the answer is in my code

 Code: b2(:,:)=b3(:,:,k)

The rest is just for illustration.
johannes

Joined: 21 Jan 2011
Posts: 65
Location: Leimen, Germany

 Posted: Tue Oct 07, 2014 8:21 am    Post subject: Hi Paul, did you want to say, that b2(:,=b3(:,:,k) does not store b2 element by element, instead it is more or less like shifting some adress? BR johannes
PaulLaidler

Joined: 21 Feb 2005
Posts: 5419
Location: Salford, UK

 Posted: Tue Oct 07, 2014 9:58 am    Post subject: No it does not move addresses. But it will significantly reduce the evaluation of the addresses. It may lead to a "block copy" rather than copying element by element. This will depend on whether or not the elements are contiguous in memory and how clever the optimiser is. (Note FTN95 does some optimisation even when /OPT is not switched on. Note also that Fortran uses "column major" ordering of array elements). The usual approach is to wrap a timer (e.g. "call system_clock(clock_count)") around the relevant code and try some experiments.
JohnCampbell

Joined: 16 Feb 2006
Posts: 1959
Location: Sydney

Posted: Wed Oct 08, 2014 11:16 am    Post subject:

You would certainly have to be careful, where you have different size arrays, such as
 Code: integer, parameter :: n=5       integer b2(n,n)       integer b3(10,10,3)         k=...         FORALL (i=1:n,j=1:n)            b2(i,j)=b3(i,j,k)         end forall

The forall would work here, but the use of (:,:) requires the same size for the first 2 dimensions.
If you are looking for a faster approach, move@ might help, although (:,:) should work well. If you need array sections, or the arrays are not the same size then you should consider an alternative, such as using move@ in a loop, such as:
do j = 1,n
call move@ ( b3(1,j,k), b2(1,j), n*4 )
end do

Another alternative could be the following without any /check option
do I = 1,n*n
b2(I,1) = b3(I,1,k)
end do

or
call move@ ( b3(1,1,k), b2, n*n*4 )
John
 Display posts from previous: All Posts1 Day7 Days2 Weeks1 Month3 Months6 Months1 Year Oldest FirstNewest First
 All times are GMT + 1 Hour Page 1 of 1