\section{Message Passing in Java}

The Java language has several built-in mechanisms which allow the
parallelism inherent in scientific programs to be exploited. Threads
and concurrency constructs are well-suited to shared memory computers,
but not large-scale distributed memory machines. Although sockets and
the RMI interface allow the development of big network applications,
they have been designed and optimized for client-server programming,
whereas the parallel computing world is mainly concerned with a more
symmetric model, where communications occur in groups of interacting
peers. Therefore, codes based on sockets and RMI would naturally
underperform platform-specific implementations of standard communication
libraries based on the successful Message Passing Interface (MPI)
standard
\cite{MPI-1}. By contrast with sockets and RMI, MPI directly supports
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.

With the evident success of Java as a programming language, and its
inevitable use in connection with parallel as well as distributed
computing, the absence of a well-designed language-specific binding for
message-passing with Java would lead to divergent, non-portable
practices. The Message-Passing Working Group of the Java Grande Forum
was formed in the Fall of 1998 as a response to the appearance of the
various APIs for message-passing.  Some of these early
``proof-of-concept'' implementations \cite{HPjava,Getov97,Judd99} have
been available since 1997 with successful ports on clusters of
workstations running Linux, Solaris, Windows NT, Irix, AIX, HP-UX, and
MacOS, as well as on parallel platforms such as the IBM SP-2 and SP-3,
Sun E4000, SGI Origin-2000, Fujitsu AP3000, Hitachi SR2201 and others.
An immediate goal was to discuss and agree on a common API for MPI-like
libraries for Message Passing in Java (MPJ) \cite{MPJ-Spec}.

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
MPJ API specification follows this model, lifting the structure of its
class hierarchy directly from the C++ binding. The purpose of this phase
of the effort is to provide an immediate, ad hoc standardization for
common message passing programs in Java, as well as to provide a basis
for conversion between C, C++, Fortran, and Java.

In this paper we present performance analysis and comparisons of
evaluation
results for both Java and C/Fortran on three different message-passing
parallel platforms -- a shared memory multi-processor (Sun E4000), a
Linux cluster, and a distributed memory computer (IBM SP-2). The NAS
parallel Embarrassingly Parallel (EP) and the Integer Sort (IS)
benchmarks
were used in our performance evaluation. The IS routine evaluates
integer
operations and bi-directional communications (the sorted keys are
exchanged
between nodes), while the EP kernel tests floating point operations
performance but requires minimal communications.

The JVM and the Java compiler used on the IBM SP-2 machine were part of
the JDK for AIX.  The execution environment consisted of IBM's Parallel
Operating Environment (POE), which supports the loading and execution of
parallel processes across the nodes of the IBM SP-2. The machine is
built of thin nodes with POWER2 Super Chip (P2SC) processors and 256
Mbytes of memory on each processor. The communication subsystem of the
SP-2 features a high-performance switch which was used throughout the
experiments.  The NAS EP and IS benchmarks were also run on a 200 MHz
dual Pentium Pro processor cluster running Linux Red Hat 6.0 on a
10baseT Ethernet.  The same experiments were performed on a 14x336 MHz
Ultra Sparc II processor Sun E4000 running Solaris 2.6. The LAM MPI
library was used on the Linux cluster, whilst both the SP-2 and the
E4000 provided native MPI libraries for message passing.

\begin{figure}[htbp]
\vspace*{-.15in}
\centerline{\epsfxsize=5in \epsffile{ep-b.eps}}
%\vspace*{-.3in}
\caption{Execution times for the NPB EP kernel
(class B) on the IBM SP-2}
\label{JavaGrande:fig:ep-b}
\end{figure}

A native code compiler for Java can be used instead of the JVM in order
to overcome the above problem. Fortunately, rapid progress is being made
in this area by developing optimizing Java compilers, such as the IBM
High-Performance Compiler for Java (HPCJ), which generates native codes
for the RS6000 architecture~\cite{HPCJ}. It works in the same manner as
compilers for C, C++, Fortran, etc. and unlike JIT compilers, the static
compilation occurs only once, before execution time. Thus, traditional
resource-intensive optimisations can be applied in order to improve the
performance of the generated native executable code. In our experiments,
we have used a version of HPCJ, which generates native code for the
RS/6000 architecture. The input of HPCJ is usually a bytecode file, but
the compiler will also accept Java source as input. In the latter case
it invokes the JDK source-to-bytecode compiler to produce the bytecode
file first. This file is then processed by a translator which
passes an intermediate language representation to the common back-end
from the family of compilers for the RS/6000 architecture. The back-end
outputs standard object code which is then linked with other object
modules and the previously bound legacy libraries to produce native
executable code.
Further experiments to evaluate the performance of the environment based
on HPCJ have been carried out with the IS kernel on an IBM SP-2 machine.
The results obtained are shown in Figure~\ref{JavaGrande:fig:is-a}.

\begin{figure}[htbp]
\vspace*{-.15in}
\centerline{\epsfxsize=5in \epsffile{is-a.eps}}
\vspace*{-.3in}
\caption{Execution time for the NPB IS kernel
(class A) on the IBM SP-2}
\label{JavaGrande:fig:is-a}
\end{figure}

Back in 1994, MPI-1 was originally designed with relatively static
platforms in mind.  To better support computing in volatile Internet
environments, modern message passing designs for Java will have to
support (at least) features such as dynamic spawning of process groups
and parallel client/server interfaces as introduced in the MPI-2
specification.  In addition, a natural framework for dynamically
discovering new compute resources and establishing connections between
running programs already exists in Sun's Jini project \cite{Arnold99},
and one line of investigation is into MPJ implementations operating in
the Jini framework.

Closely modelled as it is on the MPI standards, the existing MPJ
specification should be regarded as a first phase in a broader program
to
define a more Java-centric high performance message-passing environment.
In future a detachment from legacy implementations involving Java on top
of native methods will be emphasized.  We should consider the
possibility
of layering the messaging middleware over standard transports and other
Java-compliant middleware (like CORBA).
Of course, a primary goal in the above mentioned, both current and
future
work, should be the aim to offer MPI-like services to Java programs in
an
upward compatible fashion.  The purposes are twofold: performance and
portability.

