next up previous contents
Next: Array shape Up: Arrays Previous: Methods

Examples

Suppose p is a group and x and y are ranges distributed over dimensions of this group. We want to create a new distributed array of floating point numbers described by these parameters. A typical procedure would be

  Map [2] a_maps ;

  int size = 1 ;

  a_maps [0] = Map(x, size) ;
  size *= x.volume() ;
  a_maps [1] = Map(y, size) ;
  size *= y.volume() ;

  DAD a_frm(2, p, a_maps) ;
  float* a_dat = new float [size] ;

New dimension maps are created in the vector maps. This code implements an array with first dimension ``most-rapidly-varying'' in memorygif. After the two multiplications by Range :: volume the value accumulated in size is the total volume of the local array segment. The group and map vector are installed in a_frm and the local data segment is allocated in a_dat.

Now suppose i and j are Location objects with parent ranges x and y respectively. We want to access the array element associated with these subscripts. A typical procedure would be

  Location i(x(l1)), j(y(l2)) ;
  ...
  if(i.dim.crd() == i.crd)
    if(j.dim.crd() == j.crd) {
       ...
       a_dat [a_frm.map(0).offset(i) + a_frm.map(1).offset(j)]
       ...
    }

First we test if the element is held on the local process by looking at the coordinate field in the subscript objectsgif, then the offset member is applied to the map objects to find the offsets in the local data segment. Compared with the sort of address computations involved in accessing elements of sequential arrays, free use of calls to member functions incurs a large, frequently intolerable, performance penalty. General techniques for eliminating these penalties are discussed in section 7.

Suppose we want to set up a description of a two-dimensional section of a, with subranges of x and y (something like a(l1:u1, l2:u2) in Fortran).

  Map [2] b_maps ;

  b_maps [0] = Map(x.subrng(n1, l1), a.str(0)) ;
  b_maps [1] = Map(y.subrng(n2, l2), a.str(1)) ;
  
  DAD b_frm(2, p, b_maps) ;
  float* b_dat = a_dat ;

The memory strides and local data segment are copied from the original array. (Here n1 is u1 - l1 + 1 and n2 is u2 - l2 + 1.)

If, instead, we wanted to set up a description of a one dimensional section of a, with global subscript l1 in the first dimension, retaining the whole of the second dimension (something like a(l1, :) in Fortran) we could write

  Map [1] c_maps ;

  c_maps [0] = a.map(1) ;
  
  Location i(x(l1)) ;

  DAD c_frm(1, p / i, c_maps) ;
  float* c_dat = a_dat + a_frm.map(0).offset(i) ;

No new map objects need be created: the dimension map of the unsubscripted dimension is copied from the original array descriptor. The process group over which the section is distributed is p / i. The offset for the first dimension is added to the base address of the original arraygif. One can access element j of the section c by

  if(c_frm.grp().member())
    if(j.dim.crd() == j.crd) {
       ...
       c_dat [c_frm.map(0).offset(j)]
       ...
    }

The two examples given above easily generalize to allow construction any Fortran-90 style regular section of any distributed array.


next up previous contents
Next: Array shape Up: Arrays Previous: Methods

Guansong Zhang
Fri Oct 9 12:29:23 EDT 1998