As explained in the introduction to this chapter, an HPJava program can run under one of two models: the original multi-process model, and the multithreaded model.
Before you can run a program in multi-process mode you should install a suitable version of the mpiJava package. At the time of writing this is available for various Linux and UNIX platforms. It is possible to install mpiJava on Windows as well, but this is not well-supported in the current version 2.6. You need to go to the www.hpjava.org site and download mpiJava version 1.2.5x or later. The ``x'' is important--the extended version includes an implementation of the mpjdev API that is used in the implementation of Adlib.
Unpack the mpiJava release, and carefully read the file mpiJava/README for installation instructions.
Once you are confident mpiJava is properly installed, you should change
your CLASSPATH environment variable to remove the multithreaded
implementation of mpjdev and add the mpiJava version, e.g.
If an HPJava program is written in the style originally intended--for execution on distributed memory parallel computers--then it may be possible to run the program in either model and have it behave the same way. This is a useful property--it is very convenient to be able to debug programs in a single JVM before launching them on a network or parallel computer. However this equivalence doesn't happen automatically. It requires you to write your programs in a certain style.
First of all, and most obviously, you should avoid using standard Java thread synchronization mechanisms to communicate between the processes of an HPJava program. This may work under the multithreaded model, but it certainly won't work under the multi-process model. Two HPJava processes should not share access to a common variable. Whether they do this under the protection of synchronized methods or the synchronized statement, or whether they use volatile fields--however they do it--none of this makes any difference: it just won't work under the multi-process model.
This does not mean that individual, logical processes of an HPJava program should not be multithreaded. If a process is started up when an HPJava program is initiated, and it subsequently creates another local thread, the initiating process (or thread) can sensibly interact with the new thread through the ordinary thread synchronization features of Java. This will work under the multithreaded or the multi-process model (of course the new thread shouldn't directly interact with any of the processes of the HPJava program other than its parent process). You can see examples of this technique in the hpjdk examples suite. The Wolf program mentioned above, for one, starts a second thread in the controlling process to deal with the GUI.
These restrictions help to make sure that if a program works properly under the multithreaded model, it will subsequently work correctly under the multi-process model. There are other restrictions that go the other way.
A program running in the multi-process mode may rely on the of the per-process locality of certain ``global'' variables. In particular, in the multi-process model, each process has its own copy of every a static field (class variable) in the program. If a program is written in such a way that it depends on the process-locality of static fields, it will behave differently when the program is run under the multithreaded model. This different behavior usually manifests as a bug--typically some race condition associated with access to the unintentially shared variable.
Our recommendation is to try to avoid all use of non-constant static fields in HPJava programs. If you need per-process global variables to share information across method invocations, define the global variables as instance fields, and have the main() method create an instance of your main class. Then access the instance fields in instance methods. Many of the examples in the hpjdk example suite simply avoid global variables altogether, but see hpjdk/examples/pde2/PDE2.hpj for an example written in this style.
Sometimes you are using library functions, and it is difficult to know whether they internally use static fields. Well there is no very good solution to that problem. If you want to write code that runs under either model, you just have to be aware of the possible issues, and avoid libraries that seem likely to use and modify static fields.
It is clear that switching between the two models is not an entirely safe thing to do, and we aren't yet sure whether it is really something to be encouraged for large codes. But it is very convenient when it works. All the parallel codes in the hpjdk test suite and examples suite (except for a couple that explicitly use MPI calls) can be run in either mode.