RAI Home
    Java Tools
       Horizon Home
       Horizon 2.0
           Overview
NCSA: National Center for Supercomputing Applications
AllianceNCSAUser_InfoAccess
University of Illinois at Urbana-Champaign
Leading Edge Site

Package Summary: ncsa.horizon.arrayND

Non-Core Java packages it uses: none
Analogous Package in v1.3: n/a

Java's support for efficient access to multidimensional arrays is somewhat lacking. To make up for this shortcoming, Horizon uses the ncsa.horizon.arrayND package access and manipulate multidimensional array data.

Purpose: to provide fast, flexible access to multi-dimensional arrays by:

The ArrayND classes

The main player in this package is the abstract ArrayND class. Its interface gives access to the array elements, while hiding the details of how the elements are actually stored. It also provides methods for accessing subregions of the array. This package also provides the NDArrayIndexOutOfBoundsException, the N-dimensional analogue to the ArrayIndexOutOfBoundsException, for handling out-of-bounds conditions.

An implementation of the ArrayND class specializes in a particular storage strategy that is optimized for certain kinds of access; thus, it is very easy to mix different storage strategies within the same application. This is a particularly useful feature when your application uses different third party data readers (as Horizon does), each with their own storage strategy. All the diverse array data can be given a uniform interface by wrapping each by an appropriate ArrayND implementation.

This package currently comes with the following implementations of the ArrayND class:
NormalArrayND This implementation wraps around a normal Java multidimensional array.
ReverseNormalArrayND This implementation also wraps around a normal Java multidimensional array; however, you would use this if the ordering of the axes is reversed from you need in your application. That is, you use this class when the element that you expect to be located at array[1][2][3] is actually located at array[3][2][1].
FlatArrayND This implementation is used when the multi-dimensional data is stored in a 1-dimensional array such that the data along the first axis (e.g. the axis associated with "1" in array[1][2][3]) varies most rapidly.
NaturalFlatArrayND This implementation is used when the multi-dimensional data is stored in a 1-dimensional array such that the data along the last axis (e.g. the axis associated with "3" in array[1][2][3]) varies most rapidly. It's referred to as "Natural" because it is as if the 1-D arrays in a normal multidimensional Java array were strung together end-to-end.
VirtualSubArrayND This implementation wraps around around another ArrayND in order to give access to a subset of the array. It is as if one copied out the subset into a new ArrayND without actually doing the potentially expensive copy.

The above implementations all implement the SingleObjectStorage interface which allow the user direct access to the storage object. The FlatArrayStorage and NDArrayStorage interfaces help identify what that storage object is.

Iterating through an ArrayND

One way you might iterate through a multidimensional array is with a multidimensional array index--i.e. a 1-D integer array--which you would would use to access each element and then iterate within some loop structure. This fairly easy and efficient if you know the type and dimensionality of the array at compile-time. When you don't know these properties, you could use the ArrayND class and its getElement() method to access each element. (You could even use the VolumeIterator class to help you iterate the index.) However, this is not a very efficient way to move through your data because you would be using a random-access method to access in a non-random way. Our experience has shown this scheme to be painfully slow for large arrays.

Part of the problem with using multidimensional array data efficiently is that Java's support for array data is primarily oriented toward 1-D arrays. In particular, the Array.get() and System.arraycopy() methods treat the input arrays as 1-D arrays. The ncsa.horizon.arrayND package, therefore, takes advantage of this fact with classes that give the user access to multidimensional arrays in 1-D chunks. This allows the user to maximize the use of Array.get() and System.arraycopy() which are native methods and are therefore the fastest way to handle the data.

The two important classes used to step through the arrays are Chunkerator and ArrayChunk. A Chunkerator object holds a pointer to 1-D arrays within the storage of an ArrayND instance. As it is iterated, the pointer steps through each 1-D array in order. Access to these 1-D arrays are returned to the user in the form of an ArrayChunk which not only gives the user a reference to the 1-D array, but also instructs the how to access it in terms of a starting position, length, and stride. With this scheme, access, updating, copying, and subsampling all can be made fast and efficient. For examples of their use, see the Chunkerator and ArrayChunk APIs.

All of the above ArrayND implementations support chunking (via the Chunkable interface) and therefore can be iterated through using a Chunkerator. Our own tests have shown improvements of factors between 8 and 10 in speed over random-access schemes.

Other classes related to chunking include:
Chunkable This interface indicates that an indicates that data can be accessed in 1-D chunks.
ChunkableArrayND This is an abstract class that inherits from ArrayND and enforces chunking support by also "implementing" the Chunkable interface.
NoSuchChunkException This exception is thrown when one attempts to access a non-existant array chunk.

 


[Alliance] Alliance NCSA UIUC [NCSA]