casa
$Rev:20696$
|
00001 //# TiledLineStepper.h: Step a Vector cursor optimally through a tiled Lattice 00002 //# Copyright (C) 1997,1998,1999,2000 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: TiledLineStepper.h 20652 2009-07-06 05:04:32Z Malte.Marquarding $ 00027 00028 #ifndef LATTICES_TILEDLINESTEPPER_H 00029 #define LATTICES_TILEDLINESTEPPER_H 00030 00031 //# Includes 00032 #include <casa/aips.h> 00033 #include <lattices/Lattices/LatticeNavigator.h> 00034 #include <lattices/Lattices/LatticeIndexer.h> 00035 #include <casa/Arrays/IPosition.h> 00036 00037 00038 namespace casa { //# NAMESPACE CASA - BEGIN 00039 00040 // <summary> 00041 // Step a Vector cursor optimally through a tiled Lattice. 00042 // </summary> 00043 // <use visibility=export> 00044 00045 // <reviewed reviewer="Peter Barnes" date="1999/10/30" tests="tTiledLineStepper.cc"> 00046 // </reviewed> 00047 00048 // <prerequisite> 00049 // <li> <linkto class=LatticeNavigator> LatticeNavigator </linkto> 00050 // </prerequisite> 00051 00052 // <etymology> 00053 // TiledLineStepper is used to step a Vector cursor optimally through 00054 // a Lattice that is tiled. 00055 // </etymology> 00056 00057 // <synopsis> 00058 // When you wish to traverse a Lattice (say, a PagedArray or an Image) you 00059 // will usually create a LatticeIterator. Once created, you may attach a 00060 // LatticeNavigator to the iterator. A TiledLineStepper, is a concrete class 00061 // derived from the abstract LatticeNavigator that allows you to move 00062 // a Vector cursor through the Lattice in a way that will minimize the 00063 // amount of cache memory consumed. 00064 // <p> 00065 // Some Lattices (in particular PagedArrays) are stored (on disk) in 00066 // tiles. For an N-dimensional Lattice a tile is an N-dimensional 00067 // subsection with fewer elements along each axis. For example a Lattice of 00068 // shape [512,512,4,32] may have a tile shape of [32,16,4,16], and there 00069 // will be 16*32*1*2 (=1024) tiles in the entire Lattice. To allow efficient 00070 // access of the data in a Lattice some tiles are cached in memory. As each 00071 // tile may consume a fair bit of memory (in this example 128kBytes, 00072 // assuming each element consumes 4 bytes), it is desirable to minimise the 00073 // number of tiles held in the cache. But it is also desirable to minimise 00074 // the number of times a tiles must be read into or written from the 00075 // cache as this may require a time consuming operation like disk I/O. 00076 // <p> 00077 // Now suppose you wanted to traverse a Lattice with a Vector cursor of 00078 // length 512 pixel aligned along the x-axis. Using a 00079 // <linkto class=LatticeStepper>LatticeStepper</linkto>, each Vector is 00080 // retrieved from the Lattice sequentially and without any consideration of 00081 // the underlying tile shape. What is the optimal cache size for the above 00082 // example? 00083 // <p> 00084 // Suppose we have a cache size of 16 ie., the number of tiles along the 00085 // x-axis. Then Vectors beginning at positions [0,0,0,0] to [0,15,0,0] will 00086 // be stored in the cache. But the next Vector beginning at position 00087 // [0,16,0,0] will flush the cache and read in another 16 tiles. This I/O 00088 // takes time and will occur 16 times for each plane in the four dimensional 00089 // Lattice. Further when the cursor moves to position [0,0,1,0] the 16 tiles 00090 // that where initially in the cache will need to be read again. To avoid 00091 // all this cache I/O it is better to have a bigger cache. 00092 // <p> 00093 // Suppose the cache size is 16*32 (=512) ie., enough tiles to contain an 00094 // (x,y)-plane. Then the cache size will not be flushed until the cursor is 00095 // moved to position [0,0,0,16]. Further the cache will never need to read 00096 // back into memory tiles that had previously been stored in there. The 00097 // cache is big enough to store tiles until they have been completely 00098 // used. But this cache is 64MBytes in size, and consumes too much memory 00099 // for many computers. 00100 // <p> 00101 // This where a TiledLineStepper is useful. Because it knows the shape of the 00102 // tiles in the underlying Lattice it moves the cursor to return all the 00103 // Vectors in the smallest possible cache of tiles before moving on to the 00104 // next set of tiles. Using the above example again, the TiledLineStepper will 00105 // move the beginning of the Vector cursor in the following pattern. 00106 // <srcblock> 00107 // [0,0,0,0], [0,1,0,0], [0,2,0,0], ... [0,15,0,0] 00108 // [0,0,1,0], [0,1,1,0], ... [0,15,1,0], 00109 // ... [0,15,3,0], 00110 // [0,0,0,1], ... [0,15,3,15] 00111 // </srcblock> 00112 // Moving the Vector cursor through all 16*4*16 (=1024 positions) can be 00113 // done by caching only 16 tiles in memory (those along the x-axis). Hence 00114 // the cache size need only be 2MBytes in size. Further once all 1024 00115 // vectors have been returned it is not necessary to read these 16 tiles 00116 // back into memory. All the data in those tiles has already been 00117 // accessed. Using a TiledLineStepper rather than a LatticeStepper has, 00118 // in this example, resulted in a drop in the required cache size from 00119 // 64MBytes down to 2MBytes. 00120 // <p> 00121 // In constructing a TiledLineStepper, you specify the Lattice shape, the 00122 // tile shape and the axis the Vector cursor will be aligned with. Specifying 00123 // an axis=0 will align the cursor with the x-axis and axis=2 will produce a 00124 // cursor that is along the z-axis. The length of the cursor is always the 00125 // same as the number of elements in the Lattice along the axis the cursor 00126 // is aligned with. 00127 // <br>It is possible to use the function <src>subSection</src> to 00128 // traverse only a subsection of the lattice. 00129 // <p> 00130 // The cursor position can be incremented or decremented to retrieve the next 00131 // or previous Vector in the Lattice. The position of the next Vector in the 00132 // Lattice will depend on the tile shape, and is described above. Within a tile 00133 // the Vector cursor will move first through the x-axis and then the y-axis 00134 // (assuming we have a cursor oriented along the z-axis). In general the lower 00135 // dimensions will be exhausted (within a tile) before moving the cursor 00136 // through higher dimensions. This intra-tile behaviour for cursor movement 00137 // extends to the inter-tile movement of the cursor between tiles. 00138 // </synopsis> 00139 00140 // <example> 00141 // This example is of a global function that will do a 2-D inplace 00142 // complex Fourier transform of an arbitrary large Lattice (which 00143 // must have at least two dimensions). 00144 // 00145 // A two dimensional transform is done by successive one dimensional 00146 // transforms along all the rows and then all the columns in the 00147 // lattice. Scoping is used to destroy iterators once they have been 00148 // used. This frees up the cache memory associated with the cursor in each 00149 // iterator. 00150 // 00151 // <srcblock> 00152 // void FFT2DComplex (Lattice<Complex>& cArray, 00153 // const Bool direction) 00154 // { 00155 // const uInt ndim = cArray.ndim(); 00156 // AlwaysAssert(ndim > 1, AipsError); 00157 // const IPosition latticeShape = cArray.shape(); 00158 // const uInt nx=latticeShape(0); 00159 // const uInt ny=latticeShape(1); 00160 // const IPosition tileShape = cArray.niceCursorShape(); 00161 // 00162 // { 00163 // TiledLineStepper tsx(latticeShape, tileShape, 0); 00164 // LatticeIterator<Complex> lix(cArray, tsx); 00165 // FFTServer<Float,Complex> fftx(IPosition(1, nx)); 00166 // for (lix.reset();!lix.atEnd();lix++) { 00167 // fftx.fft(lix.rwVectorCursor(), direction); 00168 // } 00169 // } 00170 // { 00171 // TiledLineStepper tsy(latticeShape, tileShape, 1); 00172 // LatticeIterator<Complex> liy(cArray, tsy); 00173 // FFTServer<Float,Complex> ffty(IPosition(1, ny)); 00174 // for (liy.reset();!liy.atEnd();liy++) { 00175 // ffty.fft(liy.rwVectorCursor(), direction); 00176 // } 00177 // } 00178 // } 00179 // </srcblock> 00180 // </example> 00181 00182 // <motivation> 00183 // Moving through a Lattice by equal sized chunks, and without regard 00184 // to the nature of the data, is a basic and common procedure. 00185 // </motivation> 00186 00187 // <todo asof="1997/03/28"> 00188 // <li> Support for Matrix and higher dimensional cursors can be used. 00189 // </todo> 00190 00191 00192 class TiledLineStepper : public LatticeNavigator 00193 { 00194 public: 00195 00196 // Construct a TiledLineStepper by specifying the Lattice shape, 00197 // a tile shape and the axis along which the Vector cursor will lie 00198 // (0 means the x-axis). Is is nearly always advisable to make the 00199 // tileShape identical to the Lattice tileShape. This can be obtained by 00200 // <src>lat.niceCursorShape(lat.advisedMaxPixels())</src> 00201 // where <src>lat</src> is a Lattice object. 00202 TiledLineStepper (const IPosition& latticeShape, 00203 const IPosition& tileShape, 00204 const uInt axis); 00205 00206 // The copy constructor uses copy semantics. 00207 TiledLineStepper (const TiledLineStepper& other); 00208 00209 ~TiledLineStepper(); 00210 00211 // The assignment operator uses copy semantics. 00212 TiledLineStepper& operator= (const TiledLineStepper& other); 00213 00214 // Increment operator (postfix or prefix version) - move the cursor 00215 // forward one step. Returns True if the cursor was moved. 00216 virtual Bool operator++(int); 00217 00218 // Decrement operator (postfix or prefix version) - move the cursor 00219 // backwards one step. Returns True if the cursor was moved. 00220 virtual Bool operator--(int); 00221 00222 // Function to move the cursor to the beginning of the Lattice. Also 00223 // resets the number of steps (<src>nsteps</src> function) to zero. 00224 virtual void reset(); 00225 00226 // Function which returns "True" if the cursor is at the beginning of the 00227 // Lattice, otherwise, returns "False" 00228 virtual Bool atStart() const; 00229 00230 // Function which returns "True" if an attempt has been made to increment 00231 // the cursor beyond the end of the Lattice. 00232 virtual Bool atEnd() const; 00233 00234 // Function to return the number of steps (increments & decrements) taken 00235 // since construction (or since last reset). This is a running count of 00236 // all cursor movement (operator++ or operator--), even though 00237 // N-increments followed by N-decrements will always leave the cursor in 00238 // the original position. 00239 virtual uInt nsteps() const; 00240 00241 // Function which returns the current position of the beginning of the 00242 // cursor. The <src>position</src> function is relative to the origin 00243 // in the main Lattice. 00244 // <group> 00245 virtual IPosition position() const; 00246 // </group> 00247 00248 // Function which returns the current position of the end of the 00249 // cursor. The <src>endPosition</src> function is relative to the origin 00250 // in the main Lattice. 00251 // <group> 00252 virtual IPosition endPosition() const; 00253 // </group> 00254 00255 // Functions which returns the shape of the Lattice being iterated 00256 // through. <src>latticeShape</src> always returns the shape of the main 00257 // Lattice while <src>subLatticeShape</src> returns the shape of any 00258 // sub-Lattice defined using the <src>subSection</src> function. 00259 // <group> 00260 virtual IPosition latticeShape() const; 00261 virtual IPosition subLatticeShape() const; 00262 // </group> 00263 00264 // Function which returns the shape of the cursor. This always includes 00265 // all axes (ie. it includes degenerates axes) 00266 virtual IPosition cursorShape() const; 00267 00268 // Function which returns the axes of the cursor. 00269 virtual IPosition cursorAxes() const; 00270 00271 // Function which returns the shape of the "tile" the cursor will iterate 00272 // through before moving onto the next tile. THIS IS NOT THE SAME AS THE 00273 // TILE SHAPE USED BY THE LATTICE. It is nearly the same except that the 00274 // axis the cursor is aligned with is replaced by the shape of the Lattice 00275 // on that axis. eg., If a Lattice has a shape of [512,512,4,32] and a 00276 // tile shape of [32,16,4,16] then <src>tileShape()</src> will return 00277 // [512,16,4,16] if the cursor is along the x-axis and [32,512,4,16] if the 00278 // cursor is along the y-axis. 00279 IPosition tileShape() const; 00280 00281 // Function which returns "True" if the increment/decrement operators have 00282 // moved the cursor position such that part of the cursor beginning or end 00283 // is hanging over the edge of the Lattice. This always returns False. 00284 virtual Bool hangOver() const; 00285 00286 // Functions to specify a "section" of the Lattice to step over. A section 00287 // is defined in terms of the Bottom Left Corner (blc), Top Right Corner 00288 // (trc), and step size (inc), on ALL of its axes, including degenerate 00289 // axes. The step size defaults to one if not specified. 00290 // <group> 00291 virtual void subSection (const IPosition& blc, const IPosition& trc); 00292 virtual void subSection (const IPosition& blc, const IPosition& trc, 00293 const IPosition& inc); 00294 // </group> 00295 00296 // Return the bottom left hand corner (blc), top right corner (trc) or 00297 // step size (increment) used by the current sub-Lattice. If no 00298 // sub-Lattice has been defined (with the <src>subSection</src> function) 00299 // these functions return blc=0, trc=latticeShape-1, increment=1, ie. the 00300 // entire Lattice. 00301 // <group> 00302 virtual IPosition blc() const; 00303 virtual IPosition trc() const; 00304 virtual IPosition increment() const; 00305 // </group> 00306 00307 // Return the axis path. 00308 // See <linkto class=LatticeStepper>LatticeStepper</linkto> for a 00309 // description and examples. 00310 virtual const IPosition& axisPath() const; 00311 00312 // Function which returns a pointer to dynamic memory of an exact copy 00313 // of this instance. The pointer returned by this function must 00314 // be deleted externally. 00315 virtual LatticeNavigator* clone() const; 00316 00317 // Function which checks the internal data of this class for correct 00318 // dimensionality and consistant values. 00319 // Returns True if everything is fine otherwise returns False 00320 virtual Bool ok() const; 00321 00322 // Calculate the cache size (in tiles) for this type of access to a lattice 00323 // in the given row of the tiled hypercube. 00324 virtual uInt calcCacheSize (const IPosition& cubeShape, 00325 const IPosition& tileShape, 00326 uInt maxCacheSize, uInt bucketSize) const; 00327 00328 private: 00329 // Prevent the default constructor from being used. 00330 TiledLineStepper(); 00331 00332 00333 IPosition itsBlc; //# Bottom Left Corner 00334 IPosition itsTrc; //# Top Right Corner 00335 IPosition itsInc; //# Increment 00336 LatticeIndexer itsSubSection; //# The current subsection 00337 LatticeIndexer itsIndexer; //# For moving within a tile 00338 LatticeIndexer itsTiler; //# For moving between tiles 00339 IPosition itsIndexerCursorPos; //# The current position of the iterator. 00340 IPosition itsTilerCursorPos; //# The current position of the iterator. 00341 IPosition itsCursorShape; //# The shape of the cursor for itsIndexer 00342 IPosition itsTileShape; //# The tile shape (= itsTiler cursor shape) 00343 IPosition itsAxisPath; //# Path for traversing 00344 uInt itsNsteps; //# The number of iterator steps taken so far; 00345 uInt itsAxis; //# The axis containing the data vector 00346 Bool itsEnd; //# Is the cursor beyond the end? 00347 Bool itsStart; //# Is the cursor at the beginning? 00348 }; 00349 00350 00351 00352 } //# NAMESPACE CASA - END 00353 00354 #endif