From: razeh@symcom.math.uiuc.edu (Robert Allan Zeh)
Subject: Request for beta tests -- CM-2 C++ class
Apparently-To: comp-parallel@ux1.cso.uiuc.edu
Summary: A C++ Class for the CM-2 is available
Keywords: CM-2 C++ BETA BETA BETA BEAT BETA
Organization: University of Illinois at Urbana
Date: Tue, 6 Oct 1992 03:18:37 GMT

I have developed a *beta* version of a C++ package for the CM-2. It
consists mostly of calls to the appropriate PARIS library routines.
*The communication functionality is extremely lacking, and is not yet
finished*. I would appreciate any suggestions on this, or anything
else in the package.

It is available from math.uiuc.edu (128.174.111.3) as /pub/cm.tar.Z

The README for the package follows:

----------------------------------------------------------------------
A CM-2 C++ class library by Robert Allan Zeh (razeh@uiuc.edu).

This is a C++ class for the CM-2. It is implemented as a collection of
several C++ classes, each of which corresponds to a construct on the
CM-2.

The only header file you have to include is cm.h, and the only files
which have to be linked with are libcmc++.a, libcsrt-6.0.2, libparis2,
and -lm. Only the first one is created by this library, the last three
should all be in /usr/local/lib, but your local installation may vary.

You must call "init_cm()" before your first with(shape) statement, or
your first declaration of a pvar (parallel variable).  Your must have
a with(shape) statement before you do any CM-2 operations.

SHAPES

The first class is the shape class. The constructor is called with a
series of integers, which represent the length of each axis for the
shape.  Currently only one, two, and three dimensional shapes are
allowed, although it is easy to add higher dimensions.

For example:
	shape line(8192)
creates a shape named line with one axis 8192 elements long.

Several functions are provided to modify or inspect the current shape:

	with(shape line)	-- sets the current shape to shape line.
	end_with()		-- restore the current shape to what
				   it was before the previous with()
				   was called.
	current_shape()		-- return the current shape.
	dim()			-- return the dumper of dimensions.
	axis(int i)		-- return the length of axis i. Returns
				   -1 if i is out of bounds.
PINT


The second class is the pint class, which is a 32 bit integer on the
CM-2. A constructor is called with a shape to specify which shape the
pint belongs to:

For example:
	pint p(line)

creates a pint of shape line on the CM-2. If you omit the shape
parameter:

	pint p;

then a pint will be created of the current shape. Very bad things will
happen if there is no current shape.

All of the standard arithmetic operators are overloaded to work on the
CM-2, with the exception of the following operators:
	+=	-=	&=	^=	|=

which provide global sum, subtraction, and, exclusive or, and
logical or from the second argument. Unlike C*, these are *binary*
operators. For instance the C* fragment "while (|= to_do) ; " will not
work, because |= requires a variable in front of it. The scalar
argument is included in the function!

The % operator has been overloaded to perform a "correct" mod; it is
equivalent to %% in C*. However, this is only for operations between
a pint and a pint, or an int and a pint. % is still % for operations
between an int and an int.

You can read a specific element with the () (int axes ...) operator.
You must use the same number of arguments as there are dimensions in
the shape. Wretched things will happen if you don't do this. For
instance:

	p = pcoord(0);
	cout << p(5);

should produce a 5. However,

	cout << p(5,2);

will probably produce a core dump.	
	

Several member functions are provided:
	min(), max(), abs(), prand(), and signum()

An individual element from a pint can be read with the operator ()
(int) or operator () (int,int) operators. They return a FEint (Front
End integer), which under normal circumstances will be cast to an int.
However, if it is assigned to, the value on the CM-2 will be changed.

So, the following code works the way you'd expect it to:

	p(5) = 3;

will set the 5th element on the CM-2 to 3. Again, if you provide the
wrong number of indices, horrible things will happen.

The functions where(pint), end_where(), and everywhere(), are provided
to change the current context. They are the same as the C* where and
everywhere() statement, with the caveat that you must use end_where().



PFLOAT


The pfloat class provides you with 32 bit floating point numbers (23
significands and 8 bit exponents) on the CM-2. The declaration is
similar to pint:

	pfloat f(line)

does the same thing that it does for pint, but with it creates
parallel floats instead.

If you omit a parameter to the variable, then a pfloat will be
created of the current shape. If there is no current shape, very bad
things will happen.

All of the floating point operators are overloaded, and again the
following operators are overloaded ala C*:
	+=	-=

which provide a global sum and subtraction. Again, as with the pint
operators, these are binary operators!

The equality, inequality, and comparison operators (==, !=, <, <=, >,
>=, ||, and &&) return pints.

Several member functions are provided:

	abs(), round(), round_to_pint(), floor(),
	floor_to_pint(), ceiling(), ceiling_to_pint(), signum(),
	signum_to_pint(), truncate(), truncate_to_pint(),
	cos(), acos(), cosh(), acosh(), sin(), asin(), sinh(),
	asinh(), tan(), atan(),	tanh(), atanh(), exp(), log10(),
	log2()


The *_to_pint() functions return pints rather than pfloats. All of
these functions return pfloats, rather than modifying themselves.
There are several cases where there are PARIS calls that do so, and
are presumably faster. If anyone has suggestions on what those
function calls should look like, I'd like to hear them.

MEMORY MANAGEMENT

We use the PARIS heap operators CM_allocate_heap_field_vp_Set and
CM_deallocate_heap_field. I have assumed that these PARIS operations
are going to be faster than anything I could come up with through the
stack implementation.

Because the classes will try to use the current shape if they are
constructed without a shape argument, you cannot use them if there is
no current shape defined. If you do it anyway, unpleasant things will
happen.


HEADER FILES

There is a header file cmsr.h that overloads the following CMSR
functions so that C++ programs can use them:

	int CMSR_select_display_menu(int, int, int) 

	int CMSR_write_to_display(CMC_Pvar_t)

If you need to get at the pvar, you can do it with .cm_pvar(). If you
need to get at the bit size of the variable on the CM-2, you can do it
with bit size. For pfloats, the significand length is sbits, and the
exponent length is ebits. So:

	For the pvar of p:
		p.cm_pvar();
	the bit size:
		p.bitsize();


	For the number of bits in the exponent for f:
		f.ebits
	and the significand bits:
		f.sbits
	and the total number of bits on the CM-2 is
		f.bitsize();
		


COMMUNICATIONS


Communication facilities are provided by pint and pfloat member
functions.


Pint and pfloat have from_news(pint src, int axis, dir), where src is
the source pint or pfloat, axis specifies which axis the communication
is done along, and dir is CM_upward or CM_downward. Each processor
will grab the src pint or pfloat from a neighboring processor.


	for example:
		p1.from_news(p2, 0, CM_upward)

will move the contents of p2 into p1, along axis 0.

Pint and pfloat also have from_grid(pint src, int axis, int distance)
where src is the source variable, axis the axis to communicate along,
and distance is a signed int specifying from how far away the source
should be grabbed.

	for example:
		p1.from_grid(p2, 0, 33);			

will move p2 into p1, along axis 0, by a distance of 33.	

Some general communication functions are provided as member functions
of pint and pfloat:
	send(pint dest, pint send_address)
	send(pint dest, pint send_addresss, combiner comb)
	send_with_add(pint dest, pint send_address)
	send_with_max(pint dest, pint send_address)
	send_with_min(pint dest, pint send_address)
*	send_with_logand(pint dest, pint send_address)
*	send_with_logxor(pint dest, pint send_address)
*	send_with_logior(pint dest, pint send_address)
	send_with_overwrite(pint dest, pint send_address)
	get(pint src, pint send_address)

* - not available for pfloats.	


SUPPORT

This work was partially supported by the National Center for
Supercomputing Applications under grant number DMS910013N and utilized
the CM-2 at the National Center for Supercomputing Applications,
University of Ilinois at Urbana-Champaign.

This support would not have been possible without George Francis.

BUGS

There are no bugs. Just kidding. If you find any send some email to
razeh@uiuc.edu, and I'll take a look.




Newsgroups: comp.parallel