
\documentstyle[epsfig,graphics]{llncs}
%\documentclass{llncs}
%\usepackage{epsfig}
%\usepackage{graphics}

\begin{document}

\bibliographystyle{plain}

%\pagestyle{plain}

%\mainmatter

\title{\texttt{mpiJava}: An Object-Oriented \\ Java interface to MPI}

\author{Mark Baker\inst{1}, Bryan Carpenter\inst{2}, Geoffrey Fox\inst{2}, \\ 
        Sung Hoon Ko\inst{2} and Sang Lim\inst{2}}

\institute{School of Computer Science \\
           University of Portsmouth, \\
           Southsea, Hants, \\
           UK, PO4 8JF \\
           {\tt Mark.Baker@port.ac.uk}
%           \email{Mark.Baker@port.ac.uk}
\and
           NPAC at Syracuse University \\
           Syracuse, New York, \\
           NY 13244, USA \\
           {\tt \{dbc,gcf,shko,slim\}@npac.syr.edu}
%           \email{\{dbc,gcf,shko,slim\}@npac.syr.edu}
}

\date{January 8, 1999}

\maketitle

\begin{abstract}
A basic prerequisite for parallel programming is a good communication
API. The recent interest in using Java for scientific and engineering
application has led to several international efforts to produce a
message passing interface to support parallel computation. In this paper
we describe and then discuss the syntax, functionality and performance
of one such interface, \texttt{mpiJava}, an object-oriented Java interface to
MPI.  We first discuss the design of the \texttt{mpiJava} API and the issues
associated with its development. We then move on to briefly outline the
steps necessary to 'port' \texttt{mpiJava} onto a range of operating systems,
including Windows NT, Linux and Solaris. In the second part of the paper
we present and then discuss some performance measurements made of
communications bandwidth and latency to compare \texttt{mpiJava} on these
systems. Finally, we summarise our experiences and then briefly mention
work that we plan to undertake.
\end{abstract}

%newpage

\section{Introduction}

It is generally recognised that the vast majority of scientific and
engineering applications are written in either C, C++ or Fortran. The
recent popularity of Java has led to it being seriously considered as a
good language to develop scientific and engineering applications, and in
particular for parallel
computing\cite{PCRC}\cite{Fox1}\cite{Fox2}\cite{Getov}. Sun's claims, on
behalf of Java, that it is simple, efficient and platform-neutral - a
natural language for network programming - makes it attractive to
scientific programmers who wish to harness the collective computational
power of parallel platforms as well as  networks of workstations or PCs,
with interconnections ranging from LANs to the Internet. The
attractiveness of Java for scientific computing is being encouraged by
bodies like Java Grande\cite{JavaGrande}. The Java Grande forum has been
set up to co-ordinate the communities efforts to standardise many
aspects of Java and so ensure that its future development makes it more
appropriate for scientific programmers.

Developers of parallel applications generally use the Single Program
Multiple Data (SPMD) model of parallel computing, wherein a group of
processes cooperate by executing identical program images on local data
values.  A programmer using the SPMD model has a choice of explicit or
implicit  means to move data between the cooperating processes. Today,
the normal explicit means is via message passing and the implicit means
is via data-parallel languages, such as HPF. Although using implicit
means to develop parallel applications is generally thought to be
easier, explicit message passing is more often used. The reasons for
this are beyond the scope of this paper, but currently developers can
produce more efficient and effective parallel applications using 
message passing.

A basic prerequisite for message passing is a good communication API.
Java comes with various ready-made packages for communication, notably
an interface to BSD sockets, and the Remote Method Invocation (RMI)
mechanism.  Both these communication models are optimised for
client-server programming, whereas the parallel computing world is
mainly concerned with `symmetric' communication, occurring in groups of
interacting peers. 

This symmetric model of communication is captured in the successful
Message Passing Interface standard (MPI), established a few years ago\cite{MPI}.
MPI directly supports SPMD model of parallel computing. Reliable
point-to-point communication is provided through a shared, group-wide
communicator, instead of socket pairs. MPI allows numerous blocking,
non-blocking, buffered or synchronous communication modes. It also
provides a library of true collective operations (broadcast is the most
trivial example). An extended standard, MPI 2, allows for dynamic
process creation and access to memory in remote processes.

The existing MPI standards specify language bindings for Fortran, C and
C++. In this article we discuss a binding of MPI 1.1 for Java, and
describe an implementation using Java wrappers to invoke C MPI calls
through the Java Native Interface\cite{Gordon}. The software is
publically available from: 

\begin{verbatim}
  http://www.npac.syr.edu/projects/pcrc/mpiJava
\end{verbatim}

\subsection{Related work}

Early work by two of the current authors on Java MPI bindings is
reported in\cite{Carpenter1}\cite{Carpenter2}. In these papers we
compared various approaches to parallel programming in Java, including
sockets and MPI programming. A comparable approach to creating full Java

MPI interfaces is used by JCI\cite{Getov}, the \textit{Java-to-C
interface generator}. In JCI, Java wrappers are automatically generated
from the C MPI header. This eases the implementation work, but does not
lead to a fully object-oriented API. 

MPIJ is a completely Java-based implementation of MPI which runs as part
of the Distributed Object Group Metacomputing Architecture\cite{DOGMA}
(DOGMA). Being closely modelled on the MPI-2 C++ bindings, MPIJ
implements a large subset of MPI functionality.  MPIJ communication uses
native marshalling of primitive Java types. This technique allows MPIJ
to achieve communications speeds comparable with native MPI
implementations. \texttt{jmpi}\cite{Dincer} is an MPI environment built upon
JPVM\cite{Ferrari}, a Java-based implementation of PVM. \texttt{jmpi}, offers a
full Java API to MPI 1.1 as well as features such as thread safety and
multiple communication end-points per task. \texttt{jmpi} is a pure Java MPI
environment, but is complicated by the need to call JPVM methods.
Another recently announced Java MPI interface, called
JavaWMPI\cite{Martin}, is built upon the Windows MPI environment WMPI\cite{WMPI}.
JavaWMPI  has a very similar in structure to \texttt{mpiJava}, but the syntax of
the interface is less object-oriented and a procedural method is used to
perform polymorphism between Java datatypes.

MPI Software Technology, Inc. has also announced their intention to
deliver a commercial Java interface to MPI called JMPI\cite{Crawford}.
Java implementations of the related PVM message-passing environment have
been reported by Yalamanchilli et. al.\cite{Yalamanchilli} and The MPI
Forum\cite{MPI}. Many of the above-mentioned groups, as part of the Java
Grande forum activities, have recently published a position
paper\cite{Carpenter3} in an attempt to standardise on a single API.

\subsection{Overview of this article}

First we outline the \texttt{mpiJava} API and describe various special issues
that arise in Java. Implications of object serialization are also
explored briefly as are the difficulties due to the lack of true
multidimensional arrays in Java. 

This discussion is followed by a description of an implementation of the
proposed Java binding through a set of wrappers that use the JNI to call
existing MPI implementations. The virtues and problems of this
implementation strategy are discussed, and results of tests and
benchmarks on Solaris, Windows NT and Linux are presented.

\section{Introduction to the \texttt{mpiJava} API}

The MPI standard is explicitly object-based. The C and Fortran bindings
rely on `opaque objects' that can be manipulated only by acquiring
object handles from constructor functions, and passing the handles to
suitable functions in the library. The C++ binding specified in the MPI
2 standard collects these objects into suitable class hierarchies and
defines most of the library functions as class member functions. The
\texttt{mpiJava} API follows this model, lifting the structure of its class
hierarchy directly from the C++ binding. The major classes of \texttt{mpiJava}
are illustrated in Figure \ref{hierarchy}. 

\begin{figure}[bt]
\centerline{\epsfig{figure=mpiJava.eps,width=4.5in}}
\caption{Principal classes of \texttt{mpiJava}\label{hierarchy}}
\end{figure}


%\begin{figure}[bt]
%\centerline{
%  \includegraphics*[0mm,0mm][145mm,72mm]{mpiJava.eps}
%}
%\caption{Principal classes of \texttt{mpiJava}\label{hierarchy}}
%\end{figure}

The class MPI only has static members. It acts as a module containing
global services, such as initialization of MPI, and many global
constants including the default communicator \texttt{COMM\_WORLD}. 

The most important class in the package is the communicator class
\texttt{Comm}. All communication functions in \texttt{mpiJava} are
members of \texttt{Comm} or its subclasses. As usual in MPI, a
communicator stands for a 'collective object' logically shared by a
group of processors. The processes communicate, typically by addressing
messages to their peers through the common communicator. 

Another class that is important for the discussion below is the 
\texttt{Datatype} class. This describes the type of the elements in the
message buffers passed to send, receive, and all other communication
functions. Various basic datatypes are predefined in the package. These
mainly correspond to the primitive types of Java, shown in Figure
\ref{basic}.

\begin{figure}[]
\centerline{
\begin{tabular}{| l | l |} \hline
MPI datatype & Java datatype \\
\hline
MPI.BYTE     & {\tt byte} \\
MPI.CHAR     & {\tt char} \\
MPI.SHORT    & {\tt short} \\
MPI.BOOLEAN  & {\tt boolean} \\
MPI.INT      & {\tt int} \\
MPI.LONG     & {\tt long} \\
MPI.FLOAT    & {\tt float} \\
MPI.DOUBLE   & {\tt double} \\
MPI.PACKED   &  \\
\hline
\end{tabular}
}
\caption{Basic datatypes of \texttt{mpiJava}\label{basic}}
\end{figure}

The standard send and receive operations of MPI are members of \texttt{Comm} with
interfaces:\linebreak

\begin{verbatim}

public void Send(Object buf, int offset, int count, Datatype
                 datatype, int dest, int tag)

public Status Recv(Object buf, int offset, int count, Datatype
                   datatype, int source, int tag)

\end{verbatim}

In both cases the actual argument corresponding to buf must be a Java
array. In the current implementation they must be arrays with elements
of primitive type. By implication they must be one-dimensional arrays,
because Java 'multidimensional arrays' are really arrays of arrays. In
these and all other \texttt{mpiJava} calls, the buffer array argument is followed
by an offset that specifies the element of in array where the message
actually starts. 

\subsection{Special features of the Java binding }

The \texttt{mpiJava} API is modelled as closely as practical on the C++
binding defined in the MPI 2.0 standard (currently we only support the
MPI 1.1 subset). A number of changes to argument lists are forced by of
the restriction that arguments cannot be passed by reference in Java. In
general outputs of \texttt{mpiJava} methods come through the result
value of the function. In many cases MPI functions return more than one
value. This is dealt with in \texttt{mpiJava} in various ways. Sometimes
an MPI function initializes some elements in an array and also returns a
count of the number of elements modified. In Java we typically return an
array result, omitting the count. The count can be obtained subsequently
from the \texttt{length} member of the array. Sometimes an MPI function
initializes an object conditionally and returns a separate flag to say
if the operation succeeded. In Java we return an object handle which is
\texttt{null} if the operation fails. Occasionally an extra field is
added to an existing MPI class to hold extra results - for example the
\texttt{Status} class has an extra field, index, initialized by
functions like \texttt{Waitany}. Rarely none of these methods work and
we resort to defining auxilliary classes to hold multiple results from a
particular function. In another change to C++, we often omit array size
arguments, because they can be picked up within the wrapper by reading
the \texttt{length} member of the array argument.

\begin{figure}[bt]
\small
\begin{verbatim}

// Simple program

import mpi.*; 

class Hello { 
  static public void main(String[] args){
    MPI.Init(args); 
    int myrank = MPI.COMM_WORLD.Rank(); 
    if(myrank == 0)}
      char [] message = "Hello, there".toCharArray() ; 
      MPI.COMM_WORLD.Send(message,0,message.length, MPI.CHAR, 1, 99); 
    } else {
      char [] message = new char [20] ; 
      MPI.COMM_WORLD.Recv(message, 0, 20, MPI.CHAR, 0, 99) ; 
      System.out.println("received:" + new String(message) + ":"); 

    }
    MPI.Finalize(); 
  }
}

\end{verbatim}
\normalsize
\caption{Minimal \texttt{mpiJava} program (run in two processes)\label{hello}}
\end{figure}

As a result of these changes \texttt{mpiJava} argument lists are often more
concise than the corresponding C or C++ argument lists. 

Normally in \texttt{mpiJava}, MPI destructors are called by the Java
\texttt{finalize} method for the class. This is invoked automatically by
the Java garbage collector. For most classes, therefore, no binding of
the \texttt{MPI\_class\_FREE} function appears in the Java API.
Exceptions are \texttt{Comm} and \texttt{Request}, which do have
explicit \texttt{Free} members. In those cases the MPI operation could
have observable side-effects (beyond simply freeing resources), so their
execution is left under direct control of the programmer.

\subsection{Derived datatype vs Object serialization }

In MPI new \emph{derived types} of class \texttt{Datatype} can be
created using suitable library functions. The derived types allow one to
treat contiguous, strided, or indirectly indexed segments of program
arrays as individual message elements. The corresponding array
subsections can then be communicated in a single function call,
potentially exploiting any special hardware or software the platform
provides for exchanging scattered data between user space and the
communication system. 

Currently \texttt{mpiJava} provides all the derived datatype
constructors of standard MPI, with one limitation: it places significant
restrictions on its binding of \texttt{MPI\_TYPE\_STRUCT}. In C or
Fortran this function can be used to describe an entity combining fields
of different primitive (or derived) type. Because of the assumption that
buffers are one-dimensional arrays with elements of primitive type,
\texttt{mpiJava} imposes a restriction that all the types combined by
its \texttt{Datatype.Struct} member must have the same \emph{base type},
which must agree with the element type of the buffer array. Also
\texttt{mpiJava} does not provide an analogue of \texttt{MPI\_BOTTOM}
buffer address, or the \texttt{MPI\_ADDRESS} function for finding
offsets relative to this absolute member base. In C or Fortran these
functions allow buffers to include fields from separately declared
variables or arrays, but the mechanism does not sit well with the
pointer-free Java language model. 

Approaches based on the MPI derived datatype model do not seem to be the
best way to alleviate this restriction. A better option is probably to
exploit the run-time type information already provided in Java objects.
We are developing a version of \texttt{mpiJava} that adds one new predefined
datatype:

\texttt{MPI.Object} 

A message buffer can then be an array of any serializable Java objects.
The objects are serialized automatically in the wrapper of send
operations, and unserialized at their destination. 

The absence of true multi-dimensional arrays in Java limits another use
of derived data types. In MPI the \texttt{MPI\_TYPE\_VECTOR} function
creates a derived datatype representing a strided section of an array.
In C or Fortran this strided section can be identified with a section of
a multi-dimensional array. It could describe, say, an edge of the local
patch of a two-dimensional distributed array. In Java there is no
equivalence between a multi-dimensional array and a contiguous patch of
memory, or a one-dimensional array. The programmer may choose to
linearize all multi-dimensional arrays in the algorithm, representing
them as one-dimensional arrays with suitable index expressions. In this
case derived datatypes can be used to send and receive sections of the
array. Alternatively the programmer may use Java arrays of arrays to
represent multi-dimensional arrays. This simplifies the index arithmetic
in the program. Sections of the array are then explicitly copied to
one-dimensional buffers for communication. The latter option seems to be
more popular with programmers.

Although, for reasons of conformance of with MPI standards, we expect to
continue supporting derived datatypes in \texttt{mpiJava}, their value in the
Java domain is less clear-cut than in C or Fortran. Allowing
serializable objects as buffer elements is probably a more powerful
facility. 

\section{\texttt{mpiJava} implementations on PC Platforms}

\subsection{Introduction\label{problem}}

As Java is a platform-neutral language there is much interest in
'porting' \texttt{mpiJava} to PC-based systems, in particular Windows NT
and Linux. To 'port' \texttt{mpiJava} onto a PC environment it is
necessary to have a native MPI library, a version of the Java
Development Toolkit (JDK) and a C compiler. \texttt{mpiJava} consists of
two main parts: the MPI Java classes and the C stubs that binds the MPI
Java classes to the underlying native MPI implementation.  We create
these C stubs using JNI - the means by which Java can call and pass
parameters to and from a native API. Figure \ref{Layers} provides a
simple schematic view of the software layers involved.

To 'port' \texttt{mpiJava} onto a new platform, generally two steps need to be undertaken:

\begin{itemize}

\item Create a native library out of the compiled JNI C stubs.

\item Compile MPI Java in class libraries - ensuring that the correctly named
stub library is loaded by the Java \texttt{System.loadLibrary("stublib")} call in
the main source file \texttt{MPI.java}.

\end{itemize}

The development and testing of \texttt{mpiJava} was undertaken on various Sun and
SGI UNIX platforms using MPICH.  As interfacing Java to MPI is not
always trivial, in earlier implementation we often saw low-level
conflicts between the Java runtime and the interrupt mechanisms used in
the MPI implementations. The situation is improving as the JDK matures,
in particular version 1.2$\beta$ allows the use of \emph{green} or native threads,
which have eliminated the interrupt problem that we encountered with
earlier releases of the JDK. \texttt{mpiJava} is now stable on NT platforms using
WMPI and JDK 1.1 or later as well as UNIX platforms using MPICH and JDK
1.2$\beta$.

\subsection{Windows NT}

To test \texttt{mpiJava} under Windows NT we had the choice of a number of MPI
implementations to pick from\cite{Baker}. We chose WMPI  from the
Instituto Supererior de Engenharia de Coimbra, Portugal. WMPI is a full
implementation of MPI for Microsoft Win32 platforms. WMPI is based on
MPICH and includes a p4\cite{Butler}  device standard. P4 provides the
communication internals and a startup mechanism. The WMPI package is a
set of libraries (for Borland C++, Microsoft Visual C++ and Microsoft
Visual FORTRAN). The release of WMPI provides libraries, header files,
examples and daemons for remote start-up. WMPI can co-exist and interact
with MPICH/ch\_p4 in a cluster of mixed UNIX and Win32 platforms. WMPI
is still under development and is freely available. 

%\begin{figure}[bt]
%\centerline{
%  \includegraphics*[0mm,0mm][88mm,89mm]{Layers.bmp}
%}
%\caption{Software Layers\label{Layers}}
%\end{figure}

\begin{figure}[bt]
\centerline{\epsfig{figure=Layers.eps,width=1.5in}}
\caption{Software Layers\label{Layers}}
\end{figure}

\subsubsection{mpiJava under WMPI: }

To create a release of \texttt{mpiJava} for WMPI the following steps were undertaken:

\begin{itemize}

\item \emph{Step 1} - Compile the \texttt{mpiJava} JNI C interface into a Win32 Dynamic
Link Library (\texttt{mpiJava.dll}).

\item \emph{Step 2} - Modify the name of the library loaded by the \texttt{mpiJava}
interface (\texttt{MPI.java}) to that of the of the newly compiled library.

\item \emph{Step 3} - Compile the Java MPI interface into class libaries.

\item \emph{Step 4} - Create a JNI interface to WMPI. This was necessary
as under WMPI a master process is first spawned. Its purpose is to first
read in a job configuration file and use the information within it to
set up and run the actual MPI processes. An idiosyncrasy of WMPI is that
all MPI processes must have a file name with the extension \emph{.EXE}. This
led to the need to produce a JNI to WMPI so that the JVM was loaded and
the 'main' method of \texttt{mpiJava} Java class started. 

\end{itemize}

\subsection{Linux}

At the time of writing this paper, our attempts to 'port' \texttt{mpiJava} to
Linux are in progress. We are currently experiencing problems similar to
those encountered  during our early attempts to create the interface on
Solaris, mentioned in section \ref{problem} . Sun's releases the JDK for Solaris
and NT platforms first. On other platforms, such as Linux, it is
necessary for  developers to 'port' the JDK. The most recent release of
the JDK for Linux is 1.1.7 and this is version is known to be the cause
of our problems. It is anticipated that JDK 1.2 will be available for
Linux shortly and that we will be able to report our  experiences with
Linux at the IPPS/SPDP 99 workshop in April 1999.

\subsection{Functionality Tests}

An integral part of the development of this project was to produce or
translate a number of basic MPI test codes to \texttt{mpiJava}. An obvious
starting point was the C test suite originally developed by IBM . This
suite had been modified to comply fully with the MPI standard and to be
compatible with the MPICH. The suite consists of fifty-seven C programs
that test the following MPI calls and data types; collective operations,
communicators, data types, environmental inquiries, groups, point to
point and virtual topologies. These codes were all translated to
\texttt{mpiJava}.

Under WMPI and Solaris-MPICH these codes were run either as multiple
processes on a single machine (Shared Memory mode - SM) or as multiple
processes running on separate machines (Distributed Memory mode - DM).
Under WMPI and Solaris-MPICH all the codes ran in both modes without
alterations. Our experiences using Linux-MPICH will be reported when JDK
1.2 is available for Linux.

\section{Simple Communications Performance Measurement}

\subsection{Introduction}

At this early stage of our project we have decided to restrict
performance measurements to those that will give some indication of the
basic inter-processor communications performance. The actual
computational performance of each process is felt to be dependent on the
local JVM and associated technologies used by specific vendors to
increase the performance of Java.

\subsection{PingPong Communications Performance Tests }

In this program increasing sized messages are sent back and forth
between processes - this is commonly called PingPong. This benchmark is
based on standard blocking \texttt{MPI\_Send/MPI\_Recv}. PingPong provides
information about latency of \texttt{MPI\_Send/MPI\_Recv} and uni-directional
bandwidth. To ensure that anomalies in message timings are minimised the
PingPong is repeated many times for each message size. The codes used
for these tests were those developed by Baker and Grassl\cite{PingPong}.
The three existing codes (MPI-C, MPI-Fortran and Winsock-C) were used
for comparison and we implemented an \texttt{mpiJava} version for our purposes.

The main problem encountered running the PingPong code was that under
WMPI on Win32 \texttt{MPI\_Wtime()} had been implemented with a millisecond
resolution. It was necessary to adapt each of the codes to use an
alternative timer with microsecond ($\mu$s) resolution. The performance
tests shown in the next section were run on two similar systems:

\begin{itemize}

\item Two dual processor (P6 200 MHz) NT 4 workstations each with 128
MBytes of DRAM.

\item Two dual processor (UltraSparc 200 MHz) Solaris workstations with
256 MBytes of DRAM.

\end{itemize}

Both systems were connected via 10BaseT Ethernet and the tests were
carried out when there was little network activity and on quiet
machines.

\subsection{Message Startup Latencies}

\begin{table} []
  \begin{center}
    \leavevmode
    \small
    \begin{tabular}[c]{|l|l|l|l|l|l|l|l|}

    \hline
                    &
    \textbf{Wsock} &
    \textbf{WMPI-C} &
    \textbf{WMPI-J} &
    \textbf{MPICH-C} &
    \textbf{MPICH-J} &
    \textbf{Linux-C} &
    \textbf{Linux-J} \\
    \hline

    \textbf{SM }&
    144.8 $\mu$s &
    67.2  $\mu$s &
    161.4 $\mu$s & 
    148.7 $\mu$s &
    374.6 $\mu$s &
    - $\mu$s &
    - $\mu$s \\

    \hline

    \textbf{DM} &
    244.9 $\mu$s &
    623.9 $\mu$s &
    689.7 $\mu$s &
    679.1 $\mu$s &
    961.2 $\mu$s &
    - $\mu$s &
    - $\mu$s \\

    \hline

    \end{tabular}
    \normalsize
    \caption{Time for 1 Byte Messages\label{latency}}
  \end{center}
\end{table}

In Table \ref{latency} we show the transmission time in microseconds (µs) to send a
1 byte message in each of the environments tested. In SM the \texttt{mpiJava}
wrapper adds an extra 94$\mu$s (140\%) and 226$\mu$s (152\%) compared to WMPI
and MPICH C respectively. In DM the \texttt{mpiJava} wrapper adds an extra 66$\mu$s 
(11\%) and 282$\mu$s (42\%) compared to WMPI and MPICH C respectively. The
Wsock figures are those for a WinSock implementation of  PingPong
benchmark using TCP. Linux results will be presented during the
conference workshop.

\subsection{Results in Shared Memory Mode (Figure \ref{fig5})}

The \texttt{mpiJava} curve mirrors that of C with an almost constant offset up to
8K, thereafter the curves converge meeting at 256K. Under MPICH, the
curves for C and \texttt{mpiJava} mirror each other in a similar fashion to those
under WMPI, again there is a constant offset and convergence at around
256K.

\begin{figure}[bt]
\centerline{\epsfig{figure=fig5.eps,width=135mm}}
\caption{PingPong Results in Shared Memory (SM) mode\label{fig5}}
\end{figure}

%\begin{figure}[bt]
%\centerline{
%  \includegraphics*[0mm,0mm][135mm,112mm]{fig5.bmp}}
%\caption{PingPong Results in Shared Memory (SM) mode\label{fig5}}
%\end{figure}

Under WMPI the peak bandwidth of C is around 65 MBytes/s and \texttt{mpiJava} is
54 MBytes/s. The peaks occur at around 64K. Under MPICH the bandwidth is
flattening out, but still increasing for C and \texttt{mpiJava}, at the 1M. The
actual rate measured at this point is about 50 MBytes/s.

Clearly the WMPI C code perform best of those tested. The performance of
\texttt{mpiJava} in SM under WMPI is good - it exhibits a fairly constant
overhead of 95$\mu$s up to 2K, thereafter it converges with the C curve. The
performance the C code under MPICH is slightly surprising as the NT and
Solaris platforms used for these tests had similar specifications. It is
assumed that the performance reflects the usage of MPICH rather than a
native version of MPI for Solaris. Even so, the MPICH results for
\texttt{mpiJava} show that it exhibits reasonable performance.

\subsection{Results in Distributed Memory Mode (Figure \ref{fig6})}

\begin{figure}[bt]
\centerline{\epsfig{figure=fig6.eps,width=125mm}}
\caption{PingPong Results in Distributed Memory (DM) mode\label{fig6}}
\end{figure}

%\begin{figure}[bt]
%\centerline{
%  \includegraphics*[0mm,0mm][135mm,112mm]{fig6.bmp}}
%\caption{PingPong Results in Distributed Memory (DM) mode\label{fig6}}
%\end{figure}

In DM the differences between the MPI codes is not as pronounced as seen
in SM. Under WMPI the C and \texttt{mpiJava} codes display very similar
performance characteristics throughout the range tested. Under MPICH,
there is distinct performance difference between C and \texttt{mpiJava}, However
the difference is much smaller than in SM and the curves converge at the
4K. All curves peak at about 1 MByte/s, which is about 90\% of the
maximum attainable on 10 Mbps Ethernet link.

\subsection{Overall Results Discussion}

In both SM and DM modes \texttt{mpiJava} adds a fairly constant overhead compared
to normal native MPI. In an environment like WMPI, which has been
optimised for NT, the actual overheads of using \texttt{mpiJava} are relatively
small at around 100ms. Under MPICH the situation is not quite so good,
here the use of \texttt{mpiJava} introduces an extra overheads of between 250 -
300$\mu$s. 

It should be noted that these results compare codes running directly
under the operating system with those running in the JVM. For example,
according to  a single 200 MHz PentiumPro will achieve in excess of 62
Mflop/s on a Fortran version of LinPack. A test of the Java LinPack code
 gave a peak performance of 22 Mflop/s for the same processor running
the JVM. The difference in performance will account for much of the
additional overhead that \texttt{mpiJava} imposes on C MPI codes. From this it
can be deduced that the quality and performance of JVM on each platform
will have the greatest effect on the usefulness of \texttt{mpiJava} for
scientific computation.

\section{Conclusions}

\subsection{Overall Summary}

We have discussed the design and development of \texttt{mpiJava} - a pure Java
interface to MPI. We have also highlighted the benefits of a fully
object-oriented Java API compared to those currently available. Our
performance tests have shown that \texttt{mpiJava} should fulfil the needs of MPI
programmers not only in terms of functionality but also in terms of good
performance when compared to similar C MPI programs. Unfortunately, at
the time of submission of this paper we have been unable to test \texttt{mpiJava}
under Linux, but we believe that the problems we have encountered we be
overcome soon and we will be able to present our finding during the
Workshop in April 1999. Overall, however, we feel that we have
implemented a well designed, functional and efficient Java interface to
MPI.

%
% Add in Figure 6 here
%

\subsection{Particular Conclusions}

\begin{itemize}

\item \texttt{mpiJava} provides a fully functional and efficient Java interface to MPI.

\item Our performance tests have shown that, in terms of communications
speeds, WMPI on NT out performs MPICH on Solaris.

\item When used for distributed computing the current implementation of
\texttt{mpiJava} does not impose a huge overhead on-top of the native MPI
interface.

\item We have discovered some of the limitation in the usage of JNI. In
particular with MPICH where we had problems with UNIX signals. We are
hopeful that these problems will disappear when we start using JDK 1.2
and native threads.

\item Our performance tests indicate that much of the additional latency
that \texttt{mpiJava} imposes is due to the relatively poor performance
of the JVM rather than the impact of messages traversing additional
software layers.

\item The syntax of \texttt{mpiJava} is easy to understand and use, thus making it
relatively simple for programmers with either a Java or Scientific
background to take up. 

\item We believe that \texttt{mpiJava} will also provide a popular means for teaching
students the fundamentals of parallel programming with MPI.

\subsection{Future Work}

We plan to continue to improve \texttt{mpiJava} with further Java features, such
as object serialization, and also add-in the functionality that has been
proposed in MPI-2. We intend to 'port' \texttt{mpiJava} to a multitude of new MPI
environments, including LAM, Sun MPI and Globus. We are also planning a
pure-Java MPI environment which does not rely on native MPI services.

\end{itemize}

\bibliography{paper}

\end{document}

