next up previous contents
Next: Some Remarks on Parallel Up: HPJava: Work in progress. Previous: Parallel arrays and data   Contents

Applications

We need some applications. Don Leskiw has suggested a target-tracking application which combines data and task parallelism with opportunities for applet front ends. Other numerical applications of Java, suitable for parallelism, are needed.

As a trivial example of the use of our channels interface, I have ported one of the examples from the Cornell meta-computing seminar to Java. This outputs its results to files which can be viewed with xv. It should be given an applet interface. The source is included below.

--------------------------- Life.java ------------------------------

import java.io.* ;


public class Life {
  static final int N      = 64 ;
  static final int NITER  = 50 ;

  static final String [] hosts = {"koum", "naos"} ;
  static final int NNODES = hosts.length ;

  public static void main(String args[]) {
    try {
      DataInputStream fromNode [] = new DataInputStream [NNODES] ;

      // Create a ring of channels

      Port R [] = new Port [NNODES] ;
      Port S [] = new Port [NNODES] ;

      for(int i = 0 ; i < NNODES ; i++) {
        R [i] = new Port() ;
        S [i] = new Port() ;
      }

      for(int i = 0 ; i < NNODES ; i++)
        Port.channel(R [i], S [(i + 1) % NNODES]) ;

      // Create the node processes.

      for(int i = 0 ; i < NNODES ; i++) {
        Port U = new Port() ;
        Port V = new Port() ;
        Port.channel(U, V) ;

        RPC.spawn("LifeWorker", hosts [i], V) ;

        // Send parameters to node

        U.sendInt(N) ;
        U.sendInt(NITER) ;

        U.sendInt(NNODES) ;
        U.sendInt(i) ;

        U.sendChan(R [i]) ;
        U.sendChan(S [i]) ;

        fromNode [i] = new DataInputStream(new PortInputStream(U)) ; 
      }

      /*  Handle output.  */

      for(int iter = 0 ; iter <= NITER ; iter++) {

        /*  Copy current state of board from nodes to a `.pgm' file.  */

        String fname = "life" + iter / 10 + iter % 10 + ".pgm" ;
        PrintStream out = new PrintStream(new FileOutputStream(fname)) ;

        out.println("P2") ;
        out.println("" + N + "  " + N) ;
        out.println("" + 1) ;

        for(int node_id = 0 ; node_id < NNODES ; node_id++) {
          DataInputStream in = fromNode [node_id] ;

          int blockLen = in.readInt() ;

          for(int i = 0 ; i < blockLen ; i++) {
            out.print("" + in.readInt() + "  ") ;
            if(i % 20 == 19) out.println("") ;
          }
        }
      }
    }
    catch(Exception e) {
      ;
    }
  }
}


------------------------ LifeWorker.java ----------------------------


import java.io.* ;


public class LifeWorker extends Child {
  public static void main(String args[]) {
    try {
      Port R = new Port() ;
      Port S = new Port() ;

      // Get parameters from host

      int N       = initial.recvInt() ;
      int NITER   = initial.recvInt() ;

      int NNODES  = initial.recvInt() ;
      int node_id = initial.recvInt() ;

      initial.recvChan(R) ;
      initial.recvChan(S) ;

      // Create port streams

      DataOutputStream toHost =
          new DataOutputStream(new PortOutputStream(initial)) ;

      DataOutputStream toNodePrev =
          new DataOutputStream(new PortOutputStream(R)) ;
      DataInputStream fromNodePrev =
          new DataInputStream(new PortInputStream(R)) ;

      DataOutputStream  toNodeNext =
          new DataOutputStream(new PortOutputStream(S)) ;
      DataInputStream fromNodeNext =
          new DataInputStream(new PortInputStream(S)) ;

      // Define block

      int blockSizeMax = (N + NNODES - 1) / NNODES ;
      int blockBase    = blockSizeMax * node_id ;

      int blockSize ;
      if(blockBase + blockSizeMax > N)
        blockSize = N - blockBase ;
      else
        blockSize = blockSizeMax ;

      // `block' has `blockSize + 2' columns.  This allows for ghost cells.

      int block [] [] = new int [blockSize + 2] [N] ;

      for(int i = 0 ; i < blockSize ; i++) {
        int ib = i + 1 ;
        for(int y = 0 ; y < N ; y++) {
          int x = blockBase + i ;
          if(x == N / 2 || y == N / 2)
            block [ib] [y] = 1 ;
          else
            block [ib] [y] = 0 ;
        }
      }

      // Dump initial state of board to host

      toHost.writeInt(blockSize * N) ;
      for(int i = 0 ; i < blockSize ; i++) {
        int ib = i + 1 ;
        for(int y = 0 ; y < N ; y++)
          toHost.writeInt(block [ib] [y]) ;
      }
      toHost.flush() ;

      // Main update loop.

      int neighbours [] [] = new int [blockSize] [N] ;

      for(int iter = 0 ; iter < NITER ; iter++) {

        // Shift this block's upper edge into next neighbour's lower ghost edge

        for(int y = 0 ; y < N ; y++)
          toNodeNext.writeInt(block [blockSize] [y]) ;
        toNodeNext.flush() ;

        for(int y = 0 ; y < N ; y++)
          block [0] [y] = fromNodePrev.readInt() ;

        // Shift this block's lower edge into prev neighbour's upper ghost edge

        for(int y = 0 ; y < N ; y++)
          toNodePrev.writeInt(block [1] [y]) ;
        toNodePrev.flush() ;

        for(int y = 0 ; y < N ; y++)
          block [blockSize + 1] [y] = fromNodeNext.readInt() ;

        /*  Calculate a block of neighbour sums.  */

        for(int i = 0 ; i < blockSize ; i++) {
          int ib = i + 1 ;
          for(int y = 0 ; y < N ; y++) {
            int y_n = (y - 1 + N) % N ;
            int y_p = (y + 1) % N ;

            neighbours [i] [y] =
              block [ib - 1] [y_n] + block [ib - 1] [y] + block [ib - 1] [y_p] +
              block [ib]     [y_n] +                      block [ib]     [y_p] +
              block [ib + 1] [y_n] + block [ib + 1] [y] + block [ib + 1] [y_p] ;
          }
        }

        /*  Update block of board values.  */

        for(int i = 0 ; i < blockSize ; i++) {
          int ib = i + 1 ;
          for(int y = 0 ; y < N ; y++) {
            int neighbour = neighbours [i] [y] ;

            if(neighbour < 2 || neighbour > 3)
              block [ib] [y] = 0 ;
            if(neighbour == 3)
              block [ib] [y] = 1 ;
          }
        }

        /*  Dump current state of board to host */

        toHost.writeInt(blockSize * N) ;
        for(int i = 0 ; i < blockSize ; i++) {
          int ib = i + 1 ;
          for(int y = 0 ; y < N ; y++)
            toHost.writeInt(block [ib] [y]) ;
        }
        toHost.flush() ;
      }
    }
    catch(Exception e) {
      ;
    }
  }
}



Bryan Carpenter 2002-07-12