next up previous contents index
Next: Program Execution Control Up: Java Language Binding Previous: Basic Concepts   Contents   Index

Global Variables

When an SPMD program starts on a group of $n$ processes, there will be $n$ control threads mapped to $n$ physical processors. In each control thread, the program can define variables in the same way as in a sequential program. The variables created in this way are local variables. Their names may be common to all processes, but they will be accessed individually (their scope is local to a process).

Besides local variables, HPJava allows a program to define global variables, explicitly mapped to a process group. A global variable will be treated by the process group that created it as a single entity. The language has special syntax for the definition of global data. Global variables are all defined by using the new operator from free storage. When a global variable is created, a data descriptor data descriptor is also allocated to describe where the data are held. On a single processor, an array variable might be parametrized by a simple record containing a memory address and an int value for its length. On a multiprocessor, a more complicated structure is needed to describe a distributed array. The data descriptor specifies where the data is created, and how they are distributed. The logical structure of a descriptor is shown in Figure 1.2.

Figure 1.2: Descriptor.

Figure 1.3: Memory mapping.

HPJava has special syntax to define global data. The statement

  int # s = new int # on p ;
creates a global scalar replicated over process group p. In the statement, s is a data descriptor handle -- a global scalar reference global scalar reference. The scalar contains an integer value. Global scalar references can be defined for any primitive type (or, in principle, class type) of Java. The symbol # in the type signature distinguishes a global scalar from a primitive integer. For a global scalar, a field value is used to access the value:
  on(p) {
    int # s = new int # ;
    s.value = 100 ;
  }
Note how the on clause can be omitted from the constructor: the whole of the active process group is the default distribution group. Figure 1.3 shows a possible memory mapping for this scalar on different processes. Note, the value field of s is identical in each process in the distribution group. Replicated value variables are different from local variables with identical names. The associated descriptors can be used to ensure the value is maintained identically in each process, throughout program execution.

When defining a global array, it is not necessary to allocate a data descriptor for each array element--one descriptor suffices for the whole array. An array can defined with various kinds of range, introduced earlier. Suppose we have, as before,

  Range x = new BlockRange(100, p.dim(0)) ;
and the process group defined in Figure 1.1, then
  float [[]] a = new float [[x]] on q ;
will create a global array with range x on group q. Here a is a descriptor handle describing a one-dimensional array of float. It is block distributed on group q.[*] In HPJava a is called a global array reference global or distributed array reference.

A distributed array range can also be collapsed (or sequential). An integer range is specified, eg

  float [[*]] b = new float [[100]] ;
When defining an array with collapsed dimensions an asterisk is normally added in the type signatures to mark the collapsed dimensions.

The typical method of accessing global array elements is not exactly the same as for local array elements, or for global scalar references. In distributed dimensions of arrays we must use named locations as subscripts, for example

  at(i = x [3])
    a [i] = 3 ;
We will leave discussion of the at construct to Section 1.2.3, and give a simpler example here: if a global array is defined with a collapsed dimension, accessing its elements is modelled on local arrays. For example:
  for(int i = 0 ; i < 100 ; i++)
    b [i] = i ;
assigns the loop index to each corresponding element in the array.

When defining a multidimensional global array, a single descriptor parametrizes a rectangular array of any dimension:

  Range x = new BlockRange(100, p.dim(0)) ;  
  Range y = new CyclicRange(100, p.dim(1)) ;
  float [[,]] c = new float [[x, y]];
This creates a two-dimension global array with the first dimension block distributed and the second cyclic distributed. Now c is a global array reference. Its elements can be accessed using single brackets with two suitable locations inside.

The global array introduced here is a true multidimensional array, not a Java-like array-of-arrays. Java-style arrays-of-arrays are still useful. For example, one can define a local array of distributed arrays:

  int[] size = {100, 200, 400};
  float [[,]] d[] = new float [size.length][[,]] ;
  Range x[], y[];
  for (int l = 0; l < size.length; l++) {
    const int n = size [l] ;
    x[l] = new BlockRange(n, p.dim(0)) ;  
    y[l] = new BlockRange(n, p.dim(1)) ;  
    d[l] = new float [[x[l], y[l]]];
  }
This creates the stack of distributed arrays shown in Figure 1.4.

Figure 1.4: Array of distributed arrays.

Like Fortran 90, HPJava allows construction of sections of global arrays. The syntax of section subscripting uses double brackets. The subscripts can be scalar (integers or locations) or triplets.

Suppose we have array a and c defined as above. Then a[[i]], c, c[[i, 1::2]], and c[[i, :]] are all array sections. Here, i is an integer in the appropriate interval (it could also be a location in the first range of a and c). Both the expressions c[[i, 1::2]] and c[[i, :]] represent one-dimensional distributed arrays, providing aliases for subsets of the elements in c. The expression a[[i]] contains a single element of a, but the result is a global scalar reference (unlike the expression a[i] which is a simple variable).

Array section expressions are often used as arguments in function calls.[*] Table 1.1 shows the type signatures of global data with different dimensions.




Table 1.1: Section Expression and Type Signature
global var array section type
2-dimension c float [[,]]
c[[:,:]] float [[,]]
1-dimension c[[i,:]] float [[]]
c[[i,1::2]] float [[]]
scalar(0-dim) c[[i,j]] float #

The size of an array in Java can be had from its length field. In HPJava, information like the distributed group and distributed dimensions can be accessed from the following inquiries, available on all global array types:

  Group grp()       // distribution group

  Range rng(int d)  // d'th range
Further inquiry functions on Range yield values such as extents and distribution formats.


next up previous contents index
Next: Program Execution Control Up: Java Language Binding Previous: Basic Concepts   Contents   Index
Bryan Carpenter 2002-07-11