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!

use array structure with pointer application

Status
Not open for further replies.

ya0037

Programmer
Oct 7, 2010
30
DE
Hello to all,

I have a question that bothers me a lot and I could not find any answer.

I have some structures in my code, that are very useful in parallel programing using MPI, the problem is sometimes in sorting they will cause a lot of latency.

like the below one

Code:
Type person
  Sequence 
  Real(Kind = 8) :: wgt
  Real(Kind = 8) :: chg
  Real(Kind = 8) :: cnc
  Integer :: lsi
  Integer :: lsa
End Type person

Is there any way in calling a subroutine for sorting like operation instead of passing the array of one of these components passing sth like pointer. Because in my code arrays are too big and it will affect the speed very much.
I can not change the structure to normal arrays, because in parallel it is really useful for me.

I mean now I call
Code:
Call check(n, person(1:n)%lsi, person(1:n)%lsa)

So in the subroutine it has to jump across a lot to do some operation and then return it back.


Is there any way that I can call
Code:
Call check(n, person(1:n)%lsi)

and in the subroutine it gets
both
Code:
person(1)%lsi
and
Code:
person(1)%lsa
as they are sequntial and then jump to the next one
Code:
person(2)%lsi
and
Code:
person(2)%lsa
, so when I have big arrays the speed increases!!!!!!!!!!!!!!!!!!!

the idea of send sth as a new structure to the subroutine?????

Is there any way or not?

I am really looking forward to hearing your hints.

Thank you very much for your help.

Best Regards,
 
Could you show us a little how the routine Check works. Because what you ask for is a little bit confused.

For instance, I don't understand why the routine Check does not work on the array "person" directly :

CALL check(n,person(1:n))

And inside, you do want you want with person(i)%lsi and person(i)%lsa before increasing i.

In addition, it is important to see how you declare the arguments of Check. For instance, the following definition might involve performance troubles:

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1(n)
integer,intent(in) :: i2(n)
end subroutine

A better declaration would be :

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1:))
integer,intent(in) :: i2:))
end subroutine


François Jacq
 
Dear FJacq,

Hallo,

Thank you very much for your response, I always admire your answer.

About the check routine, suppose it is sorting routine that will sort lsi the rank and lsa an array of numbers based on any kind of sorting method.
The important question is that these two the rank and array are part of a very big data structure, but sequentially placed like the one I showed.

If I had more of these structures and sometimes need to do some operations on part of them like the one mentioned.
Do I get performance to send them in a subroutine like pointer value, is there any way for that or I should send them as I said above.

I have defined my subroutine like the second one.
But, could you explain me the difference between them, I do not understand?

Could you tell me which one of these shape is practically faster?
As I have many subroutines like this with very big arrays and they will be called many times, so even a slight speed would be so great for me.

Code:
Call check(n, person(1:n)%lsi, person(1:n)%lsa)
Subroutine check(n, li, la)
Integer, Intent(In) :: n
Integer, Dimension(:), Intent(In) :: li
Integer, Dimension(:), Intent(In) :: la
End Subroutine

or

Code:
Call check(n, person(:)%lsi, person(:)%lsa)
Subroutine check(n, li, la)
Integer, Intent(In) :: n
Integer, Dimension(:), Intent(In) :: li
Integer, Dimension(:), Intent(In) :: la
End Subroutine

or

Code:
Call check(n, person(:)%lsi, person(:)%lsa)
Subroutine check(n, li, la)
Integer, Intent(In) :: n
Integer, Dimension(1:*), Intent(In) :: li
Integer, Dimension(1:*), Intent(In) :: la
End Subroutine


or if I define the new structure like

Code:
Type new
Sequence
Integer :: si
Integer :: sa
End Type new

and using sth like equivalence or some kind of pointer or anything equal that with the above structure???
Which one is more efficient?

Please help me. My code although in parallel and very good, but still I need performance, it will take a long time.

I am really looking forward to hearing from you.

Best Regards,













 
I forgot to mention, I do not know whether I should pass the whole data structure to the routine or not?


It is a very big data structure, is it correct to pass the whole of it in the routine. there are lots of variables that will not be used in this subroutine, does not it take a lot of memory to that????

Thank you very much again.
 
When you declare a routine as follows :

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1(n)
integer,intent(in) :: i2(n)
end subroutine

or as synonymous :

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1(1:n)
integer,intent(in) :: i2(1:n)
end subroutine

or again :

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1(*)
integer,intent(in) :: i2(*)
end subroutine

Then you indicate the compiler that the vectors i1 and i2 contain necessarily contiguous values.

On the contrary, with the following definitions :

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1:))
integer,intent(in) :: i2:))
end subroutine

or as synonymous

subroutine check(n,i1,i2)
integer,intent(in) :: n
integer,intent(in) :: i1(1:)
integer,intent(in) :: i2(1:)
end subroutine

then the vectors i1 and i2 are not necessarily contiguous : a fixed strike between two successive elements is authorized.

Now, when you pass as actual argument for "i1" "person(1:n)%ls1", then the corresponding vector has not contiguous elements.

- If you used the first kind of version (with "n" or "*" as maximum dimension), then you force the compiler to create an intermediate vector, with contiguous elements, containing the copy of person(1:n)%ls1 ; we call that "copy in". If the dummy argument "i1" is not declared intent(in), then the compiler must also foresee a "copy out" phase after the execution of the routine, copying back the intermediate vector into person(1:n)%ls1

- On the contrary, if you use ":" as maximum dimension, then the compiler just passes the address of the first element (person(1)%ls1) and the strike equal to the length of type(person). No need of the expensive "copy in/out" technique.

In your case, the version with ":" is clearly much better. But be careful because the subroutine Check must be defined within a module else they are extra difficulties a little bit too long to explain now.

Now for you next question, if you pass the global array "person" as argument, you never duplicate that array. So there is no extra memory allocation ! One often says that Fortran passes arguments by reference or address. The example of copy in/out shows that this is not always true but this is anyway the most usual method.






François Jacq
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top