updated blue gene manual
authorGengbin Zheng <gzheng@illinois.edu>
Mon, 2 Jun 2003 07:14:21 +0000 (07:14 +0000)
committerGengbin Zheng <gzheng@illinois.edu>
Mon, 2 Jun 2003 07:14:21 +0000 (07:14 +0000)
doc/bigsim/Makefile
doc/bigsim/emulator.tex [new file with mode: 0644]
doc/bigsim/install.tex [new file with mode: 0644]
doc/bigsim/manual.tex

index 1a30decd07afc6dc316cee2eac6e7470b3237f82..83441bd4363291e923b85332ae950bd3623c66ae 100644 (file)
@@ -1,49 +1,11 @@
-DOCDIR=..
-WEBDIR=/expand8/www/ppl_manuals
+# Stub makefile for LaTeX PPL manual
+FILE=manual
+TEX=$(FILE).tex install.tex emulator.tex
 
-all: ps pdf html
+DEST=bluegene
+LATEX2HTML=$(L2H) -split 5
 
-ps:
-       touch index.tex
-       latex manual.tex
-       latex manual.tex
-       if [ -f manual.idx ] ; then makeindex -o index.tex manual.idx ; fi
-       latex manual.tex
-       dvips -o manual.ps manual.dvi
-
-html:
-       touch index.tex
-       -@ln -s ../pplmanual.* .
-       latex manual.tex
-       latex2html -local_icons manual.tex
+include ../Makefile.common
 
-pdf:
+index.tex:
        touch index.tex
-       pdflatex manual.tex
-       if [ -f manual.idx ] ; then makeindex -o index.tex manual.idx ; fi
-       pdflatex manual.tex
-
-doc:
-       make all
-       if [ ! -d $(DOCDIR) ] ; then mkdir $(DOCDIR) ; fi
-       if [ ! -d $(DOCDIR)/ps ] ; then mkdir $(DOCDIR)/ps ; fi
-       if [ ! -d $(DOCDIR)/pdf ] ; then mkdir $(DOCDIR)/pdf ; fi
-       if [ ! -d $(DOCDIR)/html ] ; then mkdir $(DOCDIR)/html ; fi
-       /bin/cp manual.ps $(DOCDIR)/ps/bluegene.ps
-       /bin/cp manual.pdf $(DOCDIR)/pdf/bluegene.pdf
-       /bin/rm -rf $(DOCDIR)/html/bluegene
-       /bin/cp -R manual $(DOCDIR)/html/bluegene
-
-web:
-       make all
-       /bin/cp manual.ps $(WEBDIR)/ps/bluegene.ps
-       /bin/cp manual.pdf $(WEBDIR)/pdf/bluegene.pdf
-       /bin/rm -rf $(WEBDIR)/html/bluegene
-       /bin/cp -R manual $(WEBDIR)/html/bluegene
-       find $(WEBDIR) -type f -exec chmod 664 {} \;
-       find $(WEBDIR) -type d -exec chmod 775 {} \;
-
-clean:
-       /bin/rm -f *.ps *.pdf *.ilg *.aux *.log *.dvi *.idx *.toc 
-       /bin/rm -f index.tex *.blg *.bbl
-       /bin/rm -rf manual
diff --git a/doc/bigsim/emulator.tex b/doc/bigsim/emulator.tex
new file mode 100644 (file)
index 0000000..b9fc533
--- /dev/null
@@ -0,0 +1,555 @@
+
+\section{Blue Gene Emulator}
+\label{bgemulator}
+
+The Blue Gene emulator environment is designed with the following
+objectives:
+
+\begin{enumerate}
+\item To support a realistic Blue Gene API on existing parallel machines
+
+\item To obtain first-order performance estimates of algorithms
+
+\item To facilitate implementations of alternate programming models for
+      Blue Gene
+\end{enumerate}
+
+The ``Blue Gene'' machine supported by the emulator consists of
+three-dimensional grid of 1-chip nodes.  The user may specify the size
+of the machine along each dimension (e.g. 34x34x36).  The chip supports
+$k$ threads (e.g. 200), each with its own integer unit.  The proximity of
+the integer unit with individual memory modules within a chip is not
+currently modeled.
+
+The API supported by the emulator can be broken down into several
+components:
+
+\begin{enumerate}
+\item Low-level API for chip-to-chip communication
+\item Mid-level API that supports local micro-tasking with a chip level
+scheduler with features such as: read-only variables, reductions, broadcasts,
+distributed tables, get/put operations
+\item Migratable objects with automatic load balancing support
+\end{enumerate}
+
+Of these, the first two have been implemented.  The simple time stamping
+algorithm, without error correction, has been implemented.  More
+sophisticated timing algorithms, specifically aimed at error correction,
+and more sophisticated features (2, 3, and others), as well as libraries
+of commonly needed parallel operations are part of the proposed work for
+future.
+
+The following sections define the appropriate parts of the API, with
+example programs and instructions for executing them.
+
+\subsection{Blue Gene Programming Environment}
+
+The basic philosophy of the Blue Gene Emulator is to hide intricate details
+of Blue Gene machine from
+application developer.Thus, the application developer needs to provide
+intialization details and handler
+functions only and gets the result as though running on a real machine.
+Communication, Thread creation,
+Time Stamping, etc are done by the emulator.
+
+\subsubsection{Blue Gene API: Level 0}
+
+\function{void addBgNodeInbuffer(bgMsg *msgPtr, int nodeID)}
+\desc{
+        low-level primitive invoked by Blue Gene emulator to put the 
+        message to the inbuffer queue of a node.
+
+        msgPtr - pointer to the message to be sent to target node; 
+
+        nodeID - node ID of the target node, it is the serial number of a 
+                 bluegene node in the emulator's physical node.
+}
+
+\function{void addBgThreadMessage(bgMsg *msgPtr, int threadID)}
+\desc{
+        add a message to a thread's affinity queue, these messages can be 
+       only executed by a specific thread indicated by threadID.
+}
+
+\function{void addBgNodeMessage(bgMsg *msgPtr)}
+\desc{
+       add a message to a node's non-affinity queue, these messages can be 
+       executed by any thread in the node.
+}
+
+\function{boolean checkReady()}
+\desc{
+        invoked by communication thread to see if there is any unattended
+        message in inBuffer.
+}
+
+\function{bgMsg * getFullBuffer()}
+\desc{
+       invoked by communication thread to retrieve the unattended message 
+       in inBuffer.
+}
+
+\function{CmiHandler msgHandlerFunc(char *msg)}
+\desc{
+       Handler function type that user can register to handle the message.
+}
+
+\function{void sendPacket(int x, int y, int z, int msgSize,bgMsg *msg)}
+\desc{
+       chip-to-chip communication function. It send a message to Node[x][y][z].
+        
+       bgMsg is the message type with message envelop used internally.
+}
+
+\subsubsection{Initialization API: Level 1a}
+
+All the functions defined in API Level 0 are used internally for the 
+implementation of bluegene node communication and worker threads.
+
+From this level, the functions defined are exposed to users to write bluegene
+program on emulator.
+
+Considering that the emulator machine will emulator several Bluegene nodes on
+each physical node, the emulator program define this function 
+\function{BgEmulatorInit(int argc, char **argv)} to initialize each emulator
+node. In this function, user program can define the Bluegene machine size,
+number of communication/worker threads, and check the command line arguments.
+
+The size of the Blue Gene machine being emulated and the number of thread per
+node is determined either by the command line arguments or calling following
+functions:
+
+\function{void BgSetSize(int sx, int sy, int sz)}
+\desc{
+       set Blue Gene Machine size;
+}
+
+\function{void BgSetNumWorkThread(int num)}
+\desc{
+       set number of worker threads per node;
+}
+
+\function{void BgSetNumCommThread(int num)}
+\desc{
+       set number of communication threads per node;
+}
+
+\function{int BgRegisterHandler(BgHandler h)}
+\desc{
+       reister user message handler functions; 
+}
+
+For each Blue Gene node, the execution starts at 
+\function{BgNodeStart(int argc, char **argv)} called by emulator for each 
+bluegene node, where application handlers can be registered and computation 
+is triggered by creating a task at required nodes.
+
+Similar to pthread's thread specifc data, each bluegene node can has its
+own node specific data associated with it. To do this, user need to define its 
+own the Node Specific Variables encapsulated in a struct definition and register
+ the pointer to the data to the emulator by following function:
+
+\function{void BgSetNodeData(char *data)}
+
+To retrieve the node specific data, call:
+
+\function{char *BgGetNodeData();}
+
+After completion of execution, user program invokes a function:
+
+\function{void BgShutdown()}
+
+to terminate the emulator.
+
+\subsubsection{Handler Function API: Level 1a}
+
+The following functions can be called in user's application program to retrie
+ve the BleneGene machine information, get thread execution time, and perform
+the communication.
+
+\function{void BgGetSize(int *sx, int *sy, int *sz);}
+
+\function{int BgGetNumWorkThread();}
+
+\function{int BgGetNumCommThread();}
+
+\function{int BgGetThreadID();}
+
+\function{double BgGetTime();}
+
+\function{void BgSendPacket(int x, int y, int z, int threadID, int handlerID, WorkType type, int numbytes, char* data);}
+\desc{
+Sends a trunk of data to Node[x,y,z] and also specifies the
+handler function to be used for this message ie. handlerID;
+threadID specifes the desired thread ID to handle the message, ANYTHREAD means
+no preference.
+specify the thread category:
+\begin{description}
+\item[1:] a small piece of work that can be done by
+communication thread itself, so NO scheduling overhead.
+\item[0:] a large piece of work, so communication thread
+schedules it for a worker thread
+\end{description}
+}
+
+
+\subsection{Writing a Blue Gene Application}
+
+\subsubsection{Application Skeleton}
+
+\begin{alltt}
+Handler function prototypes;
+Node specific data type declarations;
+
+void  BgEmulatorInit(int argc, char **argv)  function
+  Configure bluegene machine parameters including size, number of threads, etc.
+  You also neet to register handlers here.
+
+void *BgNodeStart(int argc, char **argv) function
+  The usual practice in this function is to send an intial message to trigger 
+  the execution.
+  You can also register node specific data in this function.
+
+Handler Function 1, void handlerName(char *info)
+Hanlder Function 2, void handlerName(char *info)
+..
+Handler Function N, void handlerName(char *info)
+
+\end{alltt}
+
+\subsubsection{Sample Application 1}
+
+\begin{verbatim}
+/* Application: 
+ *   Each node starting at [0,0,0] sends a packet to next node in
+ *   the ring order.
+ *   After node [0,0,0] gets message from last node
+ *   in the ring, the application ends.
+ */
+
+
+#include "blue.h"
+
+#define MAXITER 2
+
+int iter = 0;
+int passRingHandler;
+
+void passRing(char *msg);
+
+void nextxyz(int x, int y, int z, int *nx, int *ny, int *nz)
+{
+  int numX, numY, numZ;
+
+  BgGetSize(&numX, &numY, &numZ);
+  *nz = z+1; *ny = y; *nx = x;
+  if (*nz == numZ) {
+    *nz = 0; (*ny) ++;
+    if (*ny == numY) {
+      *ny = 0; (*nx) ++;
+      if (*nx == numX) *nx = 0;
+    }
+  }
+}
+
+void BgEmulatorInit(int argc, char **argv)
+{
+  passRingHandler = BgRegisterHandler(passRing);
+}
+
+/* user defined functions for bgnode start entry */
+void BgNodeStart(int argc, char **argv)
+{
+  int x,y,z;
+  int nx, ny, nz;
+  int data, id;
+
+  BgGetXYZ(&x, &y, &z);
+  nextxyz(x, y, z, &nx, &ny, &nz);
+  id = BgGetThreadID();
+  data = 888;
+  if (x == 0 && y==0 && z==0) {
+    BgSendPacket(nx, ny, nz, -1,passRingHandler, LARGE_WORK, 
+                               sizeof(int), (char *)&data);
+  }
+}
+
+/* user write code */
+void passRing(char *msg)
+{
+  int x, y, z;
+  int nx, ny, nz;
+  int id;
+  int data = *(int *)msg;
+
+  BgGetXYZ(&x, &y, &z);
+  nextxyz(x, y, z, &nx, &ny, &nz);
+  if (x==0 && y==0 && z==0) {
+    if (++iter == MAXITER) BgShutdown();
+  }
+  id = BgGetThreadID();
+  BgSendPacket(nx, ny, nz, -1, passRingHandler, LARGE_WORK, 
+                               sizeof(int), (char *)&data);
+}
+
+\end{verbatim}
+
+
+\subsubsection{Sample Application 2}
+
+\begin{verbatim}
+
+/* Application: 
+ *   Find the maximum element.
+ *   Each node computes maximum of it's elements and
+ *   the max values it received from other nodes
+ *   and sends the result to next node in the reduction sequence.
+ * Reduction Sequence: Reduce max data to X-Y Plane
+ *   Reduce max data to Y Axis
+ *   Reduce max data to origin.
+ */
+
+
+#include <stdlib.h>
+#include "blue.h"
+
+#define A_SIZE 4
+
+#define X_DIM 3
+#define Y_DIM 3
+#define Z_DIM 3
+
+int REDUCE_HANDLER_ID;
+int COMPUTATION_ID;
+
+extern "C" void reduceHandler(char *);
+extern "C" void computeMax(char *);
+
+class ReductionMsg {
+public:
+  int max;
+};
+
+class ComputeMsg {
+public:
+  int dummy;
+};
+
+void BgEmulatorInit(int argc, char **argv)
+{
+  if (argc < 2) { 
+    CmiAbort("Usage: <program> <numCommTh> <numWorkTh>\n"); 
+  }
+
+  /* set machine configuration */
+  BgSetSize(X_DIM, Y_DIM, Z_DIM);
+  BgSetNumCommThread(atoi(argv[1]));
+  BgSetNumWorkThread(atoi(argv[2]));
+
+  REDUCE_HANDLER_ID = BgRegisterHandler(reduceHandler);
+  COMPUTATION_ID = BgRegisterHandler(computeMax);
+
+}
+
+void BgNodeStart(int argc, char **argv) {
+  int x, y, z;
+  BgGetXYZ(&x, &y, &z);
+
+  ComputeMsg *msg = new ComputeMsg;
+  BgSendLocalPacket(ANYTHREAD, COMPUTATION_ID, LARGE_WORK, 
+                       sizeof(ComputeMsg), (char *)msg);
+}
+
+void reduceHandler(char *info) {
+  // assumption: THey are initialized to zero?
+  static int max[X_DIM][Y_DIM][Z_DIM];
+  static int num_msg[X_DIM][Y_DIM][Z_DIM];
+
+  int i,j,k;
+  int external_max;
+
+  BgGetXYZ(&i,&j,&k);
+  external_max = ((ReductionMsg *)info)->max;
+  num_msg[i][j][k]++;
+
+  if ((i == 0) && (j == 0) && (k == 0)) {
+    // master node expects 4 messages:
+    // 1 from itself;
+    // 1 from the i dimension;
+    // 1 from the j dimension; and
+    // 1 from the k dimension
+    if (num_msg[i][j][k] < 4) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Can report max data after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      CmiPrintf("The maximal value is %d \n", max[i][j][k]);
+      BgShutdown();
+      return;
+    }
+  } else if ((i == 0) && (j == 0) && (k != Z_DIM - 1)) {
+    // nodes along the k-axis other than the last one expects 4 messages:
+    // 1 from itself;
+    // 1 from the i dimension;
+    // 1 from the j dimension; and
+    // 1 from the k dimension
+    if (num_msg[i][j][k] < 4) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Forwards max data to node i,j,k-1 after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      ReductionMsg *msg = new ReductionMsg;
+      msg->max = max[i][j][k];
+      BgSendPacket(i,j,k-1,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+    }
+  } else if ((i == 0) && (j == 0) && (k == Z_DIM - 1)) {
+    // the last node along the k-axis expects 3 messages:
+    // 1 from itself;
+    // 1 from the i dimension; and
+    // 1 from the j dimension
+    if (num_msg[i][j][k] < 3) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Forwards max data to node i,j,k-1 after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      ReductionMsg *msg = new ReductionMsg;
+      msg->max = max[i][j][k];
+      BgSendPacket(i,j,k-1,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+    }
+  } else if ((i == 0) && (j != Y_DIM - 1)) {
+    // for nodes along the j-k plane except for the last and first row of j,
+    // we expect 3 messages:
+    // 1 from itself;
+    // 1 from the i dimension; and
+    // 1 from the j dimension
+    if (num_msg[i][j][k] < 3) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Forwards max data to node i,j-1,k after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      ReductionMsg *msg = new ReductionMsg;
+      msg->max = max[i][j][k];
+      BgSendPacket(i,j-1,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+    }
+  } else if ((i == 0) && (j == Y_DIM - 1)) {
+    // for nodes along the last row of j on the j-k plane,
+    // we expect 2 messages:
+    // 1 from itself;
+    // 1 from the i dimension;
+    if (num_msg[i][j][k] < 2) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Forwards max data to node i,j-1,k after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      ReductionMsg *msg = new ReductionMsg;
+      msg->max = max[i][j][k];
+      BgSendPacket(i,j-1,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+    }
+  } else if (i != X_DIM - 1) {
+    // for nodes anywhere the last row of i,
+    // we expect 2 messages:
+    // 1 from itself;
+    // 1 from the i dimension;
+    if (num_msg[i][j][k] < 2) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Forwards max data to node i-1,j,k after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      ReductionMsg *msg = new ReductionMsg;
+      msg->max = max[i][j][k];
+      BgSendPacket(i-1,j,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+    }
+  } else if (i == X_DIM - 1) {
+    // last row of i, we expect 1 message:
+    // 1 from itself;
+    if (num_msg[i][j][k] < 1) {
+      // not ready yet, so just find the max
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+    } else {
+      // done. Forwards max data to node i-1,j,k after making last comparison
+      if (max[i][j][k] < external_max) {
+       max[i][j][k] = external_max;
+      }
+      ReductionMsg *msg = new ReductionMsg;
+      msg->max = max[i][j][k];
+      BgSendPacket(i-1,j,k,-1,REDUCE_HANDLER_ID,LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+    }
+  }
+}
+
+void computeMax(char *info) {
+  int A[A_SIZE][A_SIZE];
+  int i, j;
+  int max = 0;
+
+  int x,y,z; // test variables
+  BgGetXYZ(&x,&y,&z);
+
+  // Initialize
+  for (i=0;i<A_SIZE;i++) {
+    for (j=0;j<A_SIZE;j++) {
+      A[i][j] = i*j;
+    }
+  }
+
+//  CmiPrintf("Finished Initializing %d %d %d!\n",  x , y , z);
+
+  // Find Max
+  for (i=0;i<A_SIZE;i++) {
+    for (j=0;j<A_SIZE;j++) {
+      if (max < A[i][j]) {
+       max = A[i][j];
+      }
+    }
+  }
+
+  // prepare to reduce
+  ReductionMsg *msg = new ReductionMsg;
+  msg->max = max;
+  BgSendLocalPacket(ANYTHREAD, REDUCE_HANDLER_ID, LARGE_WORK, 
+                               sizeof(ReductionMsg), (char *)msg);
+
+//  CmiPrintf("Sent reduce message to myself with max value %d\n", max);
+}
+
+
+\end{verbatim}
+
diff --git a/doc/bigsim/install.tex b/doc/bigsim/install.tex
new file mode 100644 (file)
index 0000000..81be8ba
--- /dev/null
@@ -0,0 +1,126 @@
+\section{Blue Gene Simulator Installation and Usage}
+\label{install}
+
+\subsection{Installing Charm++ and Blue Gene}
+
+Blue Gene Simulator now is integrated into Charm++ distribution as a runtime 
+library. Unfortunately, the precompiled binary package distribution doesnot 
+contain the Blue Gene Simulator, thus you need to download source code
+and compile yourself. 
+
+You begin by downloading Charm++ from our website:
+http://charm.cs.uiuc.edu/beta.html
+
+Please refer to "Charm++ Installation and Usage Manual" and also the README
+in the source code for detailed instruction on how to compile Charm++.
+In short, the "build" script is the main tool for compiling Charm++.
+You need to provide target and platform options:
+\begin{verbatim}
+./build <target> <platform> [options ...] [charmc-options ...]
+\end{verbatim}
+
+For example, to compile on a Linux machine, type:
+\begin{verbatim}
+./build charm++ net-linux
+\end{verbatim}
+
+which builds basic Charm++ kernel using UDP as communication method, 
+alternatively, you can build Charm++ kernel on MPI:
+\begin{verbatim}
+./build charm++ mpi-linux
+\end{verbatim}
+
+For other platforms, change net-linux to whatever platform you are compiling 
+on.
+
+However, those commands donot automatically compile for Blue Gene Simulator, 
+thus to compile both Charm++ kernel and Blue Gene Simulator, you need 
+to provide a special target and an extra option for "build" script, 
+for example:
+\begin{verbatim}
+./build bluegene net-linux bluegene
+\end{verbatim}
+
+The first "bluegene" is the compilation target, it tells "build" to
+compile Blue Gene Simulator libraries as well as Charm++ basic kernel;
+The second "bluegene" is an option to platform "net-linux", which tells
+"build" to compile the Charm++ kernel upon Blue Gene Emulator. 
+To compile AMPI on Blue Gene, use "bgampi" as target, which subsumes target
+"bluegene":
+\begin{verbatim}
+./build bgampi net-linux bluegene
+\end{verbatim}
+
+For the above "build" command, it creates a directory named 
+"net-linux-bluegene" under charm. 
+
+\subsection{Compiling Blue Gene Applications}
+
+\charmpp{} provides a compiler script {\tt charmc} to compile all programs.
+
+There are three methods to write a Blue Gene applicaiton:
+
+\subsubsection{Writing a Blue Gene application using low level machine API}
+The low level machine API mimics the actual machine low level programming
+API. It is defined in section~\ref{bgemulator}.
+
+In order to link against the Blue Gene library, specify 
+\texttt{-language bluegene} as an argument to the {\tt charmc} linker, 
+for example:
+\begin{verbatim}
+charmc -o hello hello.C -language bluegene
+\end{verbatim}
+
+Sample applications in low level machine API can be found under directory
+charm/pgms/converse/bluegene.
+
+\subsubsection{Writing a Blue Gene application using Charm++}
+
+One can also write a normal \charmpp{} application which can automatically
+run on the emulator after compilation. In order to link against the Blue Gene 
+library as well as \charmpp{} kernel libraries, specify 
+\texttt{-language charm++} as an argument to the {\tt charmc} linker:
+\begin{verbatim}
+charmc -o hello hello.C -language charm++
+\end{verbatim}
+
+Sample applications in \charmpp{} can be found under directory
+charm/pgms/charm++, specifically charm/pgms/charm++/littleMD.
+
+\subsubsection{Writing a Blue Gene application using MPI}
+
+One can also write a MPI application to run on Blue Gene Simulator.
+The Adaptive MPI, or AMPI is implemented on top of Charm++.
+
+In order to link against the Blue Gene library as well as AMPI and \charmpp{} 
+kernel libraries, specify 
+\texttt{-language ampi} as an argument to the {\tt charmc} linker:
+\begin{verbatim}
+charmc -o hello hello.C -language ampi
+\end{verbatim}
+
+Sample applications in AMPI can be found under directory
+charm/pgms/charm++/ampi, specifically charm/pgms/charm++/Cjacobi3D.
+
+\subsection{Running a Blue Gene Application}
+
+To run a parallel Blue Gene application, \charmpp{} provides a utility program
+{\tt charmrun} to start the parallel program. For detailed description on
+how to run a \charmpp{} application, refer to file charm/README in the
+source code distribution.
+
+For Blue Gene applications, you need to provide these parameters to 
+{\tt charmrun} to define the simulated Blue Gene machine size:
+\begin{enumerate}
+\item {\tt +x, +y} and {\tt +z}:  define the size of of machine in three dimensions, these define the number of nodes of a machine;
+\item {\tt +wth} and {\tt +cth}:  For one node, these parameters define the number of worker processors({\tt +wth}) and the number of communication processors({\tt +cth}).
+\end{enumerate}
+
+For example, to simulate a Blue Gene/L machine of size 64K in 40X40X40, with 
+one worker processor and one I/O processor on each node, using 100 
+real processors:
+\begin{verbatim}
+./charmrun +p100 ./hello +x40 +y40 +z40 +cth1 +wth1
+\end{verbatim}
+
+
index c5215f4aa5c96b2ef46f1667c118b4857ae012e4..af6fda4b9428f0f05ec48e5aa101ea1a3aa6c7ed 100644 (file)
 \documentclass[10pt]{article}
-\usepackage{pplmanual}
+\usepackage{../pplmanual}
 \input{../pplmanual}
 
-\title{Bluegene Emulator}
-\version{0.01}
+\title{Parallel Simulator for Large Parallel Machines}
+\version{1.00}
 \credits{Charm++ BlueGene Emulator was developed by Arun Singla, Neelam Saboo
 and Joshua Unger under the guidance of Prof. L. V. Kale. The new Converse 
-BlueGene Emulator is completely rewritten by Gengbin Zheng. Converse BlueGene 
-Emulator is the only version under maintenance now.}
+Blue Gene Emulator is completely rewritten by Gengbin Zheng. Converse Blue Gene 
+Emulator is the only version under maintenance now. Charm++ and Adaptive MPI
+(AMPI) was ported onto the Blue Gene Emulator by Gengbin Zheng. The parallel
+performance simulator was developed by Gengbin Zheng and 
+Gunavardhan Kakulapati.}
 
 \begin{document}
 \maketitle
 
 \section{Introduction}
 
-Blue Gene is a proposed one million processor machine from IBM.
+One approach for building the next generation of parallel computers
+is based on large aggregates of multiprocessor chips with support
+for hardware multithreading. 
+An initial design for IBM's Blue Gene/C project exemplifies this approach.
+Blue Gene/C was a proposed one million processor machine from IBM.
 
-The Blue Gene emulator environment is designed with the following
-objectives:
+It is important that one can study the programming issues and performance
+of paralle applications on such machines even before the machine is built.
+Thus, we have developed a parallel simulator to facilitate this research.
 
-\begin{enumerate}
-\item To support a realistic Blue Gene API on existing parallel machines
-
-\item To obtain first-order performance estimates of algorithms
-
-\item To facilitate implementations of alternate programming models for
-      Blue Gene
-\end{enumerate}
+Since our research was initiated by Blue Gene/C project, in this manual, 
+we also call our simulator as Blue Gene Simulator.
+Our simulator is capable of simulating a broad class of "Massively Parallel
+Processors-In-Memory", or MPPIMs machines. 
 
-The ``Blue Gene'' machine supported by the emulator consists of
-three-dimensional grid of 1-chip nodes.  The user may specify the size
-of the machine along each dimension (e.g. 34x34x36).  The chip supports
-$k$ threads (e.g. 200), each with its own integer unit.  The proximity of
-the integer unit with individual memory modules within a chip is not
-currently modeled.
-
-The API supported by the emulator can be broken down into several
-components:
+\subsection{Simulator system components:}
 
+Our simulator system includes these components: 
 \begin{enumerate}
-\item Low-level API for chip-to-chip communication
-\item Mid-level API that supports local micro-tasking with a chip level
-scheduler with features such as: read-only variables, reductions, broadcasts,
-distributed tables, get/put operations
-\item Migratable objects with automatic load balancing support
+\item a parallel emulator which emulates the low level machine API; 
+\item a message driven programming language (Charm++) running on top of the emulator; 
+\item adaptive MPI (an implementation of MPI on top of Charm++) environment; 
+\item a parallel simulator for performance prediction. 
 \end{enumerate}
 
-Of these, the first two have been implemented.  The simple time stamping
-algorithm, without error correction, has been implemented.  More
-sophisticated timing algorithms, specifically aimed at error correction,
-and more sophisticated features (2, 3, and others), as well as libraries
-of commonly needed parallel operations are part of the proposed work for
-future.
-
-The following sections define the appropriate parts of the API, with
-example programs and instructions for executing them.
-
-\section{History}
-
-The first version of BlueGene emulator was written on Charm++, a 
-parallel object language. 
-
-The second version of Blue Gene emulator is now 
-completely rewritten on top of Converse instead of Charm++, while the API 
-supported by the original emulator is kept without major changes. The new 
-emulator is implemented on a lower layer communication library - Converse 
-in order to achieve better performance by avoiding the cross layer overhead. 
-Switching to Converse Blue Gene emulator allows further porting of Charm++ 
-parallel language on the emulator. 
-
-New features are also added in the Converse Blue Gene emulator including 
-supporting thread-committed messages that can be send to a specific thread 
-in a Blue Gene node; supporting Bluegene node level broadcast. 
-
-\section{Blue Gene Programming Environment}
-
-The basic philosophy of the Blue Gene Emulator is to hide intricate details
-of Blue Gene machine from
-application developer.Thus, the application developer needs to provide
-intialization details and handler
-functions only and gets the result as though running on a real machine.
-Communication, Thread creation,
-Time Stamping, etc are done by the emulator.
-
-\subsection{Blue Gene API: Level 0}
-
-\function{void addBgNodeInbuffer(bgMsg *msgPtr, int nodeID)}
-\desc{
-        low-level primitive invoked by Blue Gene emulator to put the 
-        message to the inbuffer queue of a node.
-
-        msgPtr - pointer to the message to be sent to target node; 
-
-        nodeID - node ID of the target node, it is the serial number of a 
-                 bluegene node in the emulator's physical node.
-}
-
-\function{void addBgThreadMessage(bgMsg *msgPtr, int threadID)}
-\desc{
-        add a message to a thread's affinity queue, these messages can be 
-       only executed by a specific thread indicated by threadID.
-}
-
-\function{void addBgNodeMessage(bgMsg *msgPtr)}
-\desc{
-       add a message to a node's non-affinity queue, these messages can be 
-       executed by any thread in the node.
-}
-
-\function{boolean checkReady()}
-\desc{
-        invoked by communication thread to see if there is any unattended
-        message in inBuffer.
-}
-
-\function{bgMsg * getFullBuffer()}
-\desc{
-       invoked by communication thread to retrieve the unattended message 
-       in inBuffer.
-}
-
-\function{CmiHandler msgHandlerFunc(char *msg)}
-\desc{
-       Handler function type that user can register to handle the message.
-}
-
-\function{void sendPacket(int x, int y, int z, int msgSize,bgMsg *msg)}
-\desc{
-       chip-to-chip communication function. It send a message to Node[x][y][z].
-        
-       bgMsg is the message type with message envelop used internally.
-}
-
-\subsection{Initialization API: Level 1a}
-
-All the functions defined in API Level 0 are used internally for the 
-implementation of bluegene node communication and worker threads.
-
-From this level, the functions defined are exposed to users to write bluegene
-program on emulator.
-
-Considering that the emulator machine will emulator several Bluegene nodes on
-each physical node, the emulator program define this function 
-\function{BgEmulatorInit(int argc, char **argv)} to initialize each emulator
-node. In this function, user program can define the Bluegene machine size,
-number of communication/worker threads, and check the command line arguments.
-
-The size of the Blue Gene machine being emulated and the number of thread per
-node is determined either by the command line arguments or calling following
-functions:
-
-\function{void BgSetSize(int sx, int sy, int sz)}
-\desc{
-       set Blue Gene Machine size;
-}
-
-\function{void BgSetNumWorkThread(int num)}
-\desc{
-       set number of worker threads per node;
-}
-
-\function{void BgSetNumCommThread(int num)}
-\desc{
-       set number of communication threads per node;
-}
-
-\function{int BgRegisterHandler(BgHandler h)}
-\desc{
-       reister user message handler functions; 
-}
-
-For each Blue Gene node, the execution starts at 
-\function{BgNodeStart(int argc, char **argv)} called by emulator for each 
-bluegene node, where application handlers can be registered and computation 
-is triggered by creating a task at required nodes.
-
-Similar to pthread's thread specifc data, each bluegene node can has its
-own node specific data associated with it. To do this, user need to define its 
-own the Node Specific Variables encapsulated in a struct definition and register
- the pointer to the data to the emulator by following function:
-
-\function{void BgSetNodeData(char *data)}
-
-To retrieve the node specific data, call:
-
-\function{char *BgGetNodeData();}
-
-After completion of execution, user program invokes a function:
-
-\function{void BgShutdown()}
-
-to terminate the emulator.
-
-\subsection{Handler Function API: Level 1a}
-
-The following functions can be called in user's application program to retrie
-ve the BleneGene machine information, get thread execution time, and perform
-the communication.
-
-\function{void BgGetSize(int *sx, int *sy, int *sz);}
-
-\function{int BgGetNumWorkThread();}
-
-\function{int BgGetNumCommThread();}
-
-\function{int BgGetThreadID();}
-
-\function{double BgGetTime();}
-
-\function{void BgSendPacket(int x, int y, int z, int threadID, int handlerID, WorkType type, int numbytes, char* data);}
-\desc{
-Sends a trunk of data to Node[x,y,z] and also specifies the
-handler function to be used for this message ie. handlerID;
-threadID specifes the desired thread ID to handle the message, ANYTHREAD means
-no preference.
-specify the thread category:
-\begin{description}
-\item[1:] a small piece of work that can be done by
-communication thread itself, so NO scheduling overhead.
-\item[0:] a large piece of work, so communication thread
-schedules it for a worker thread
-\end{description}
-}
-
-
-\section{Writing a Blue Gene Application}
-
-\subsection{Application Skeleton}
-
-\begin{alltt}
-Handler function prototypes;
-Node specific data type declarations;
+\subsection{History}
 
-void  BgEmulatorInit(int argc, char **argv)  function
-  Configure bluegene machine parameters including size, number of threads, etc.
-  You also neet to register handlers here.
+The first version of Blue Gene emulator was first written in Charm++, a 
+parallel object language in fall, 2001. 
 
-void *BgNodeStart(int argc, char **argv) function
-  The usual practice in this function is to send an intial message to trigger 
-  the execution.
-  You can also register node specific data in this function.
+The second version of Blue Gene emulator was completely rewritten on top 
+of Converse instead of Charm++ in spring 2002. 
+While the API supported by the original emulator remains almost same,
+many new features were added - support of thread-committed messages that 
+can be send to a specific thread in a Blue Gene node; support of Blue Gene 
+node level broadcast.
+The new emulator was implemented on a lower layer communication 
+library - Converse in order to achieve better 
+performance by avoiding the cross layer overhead. 
+Another advantage is that the lighter weighted emulator makes it easier
+to port higher level of programming language onto the emulator.
 
-Handler Function 1, void handlerName(char *info)
-Hanlder Function 2, void handlerName(char *info)
-..
-Handler Function N, void handlerName(char *info)
+In the following sections, we will first describe how to download and compile
+Blue Gene simulator(Sec. ~\ref{install}). Section~\ref{bgemulator} will describe
+the low level machine API in detail. 
 
-\end{alltt}
 
-\subsection{Sample Application 1}
-
-\begin{verbatim}
-/* Application: 
- *   Each node starting at [0,0,0] sends a packet to next node in
- *   the ring order.
- *   After node [0,0,0] gets message from last node
- *   in the ring, the application ends.
- */
-
-
-#include "blue.h"
-
-#define MAXITER 2
-
-int iter = 0;
-int passRingHandler;
-
-void passRing(char *msg);
-
-void nextxyz(int x, int y, int z, int *nx, int *ny, int *nz)
-{
-  int numX, numY, numZ;
-
-  BgGetSize(&numX, &numY, &numZ);
-  *nz = z+1; *ny = y; *nx = x;
-  if (*nz == numZ) {
-    *nz = 0; (*ny) ++;
-    if (*ny == numY) {
-      *ny = 0; (*nx) ++;
-      if (*nx == numX) *nx = 0;
-    }
-  }
-}
-
-void BgEmulatorInit(int argc, char **argv)
-{
-  passRingHandler = BgRegisterHandler(passRing);
-}
-
-/* user defined functions for bgnode start entry */
-void BgNodeStart(int argc, char **argv)
-{
-  int x,y,z;
-  int nx, ny, nz;
-  int data, id;
-
-  BgGetXYZ(&x, &y, &z);
-  nextxyz(x, y, z, &nx, &ny, &nz);
-  id = BgGetThreadID();
-  data = 888;
-  if (x == 0 && y==0 && z==0) {
-    BgSendPacket(nx, ny, nz, -1,passRingHandler, LARGE_WORK, 
-                               sizeof(int), (char *)&data);
-  }
-}
-
-/* user write code */
-void passRing(char *msg)
-{
-  int x, y, z;
-  int nx, ny, nz;
-  int id;
-  int data = *(int *)msg;
-
-  BgGetXYZ(&x, &y, &z);
-  nextxyz(x, y, z, &nx, &ny, &nz);
-  if (x==0 && y==0 && z==0) {
-    if (++iter == MAXITER) BgShutdown();
-  }
-  id = BgGetThreadID();
-  BgSendPacket(nx, ny, nz, -1, passRingHandler, LARGE_WORK, 
-                               sizeof(int), (char *)&data);
-}
-
-\end{verbatim}
-
-
-\subsection{Sample Application 2}
-
-\begin{verbatim}
-
-/* Application: 
- *   Find the maximum element.
- *   Each node computes maximum of it's elements and
- *   the max values it received from other nodes
- *   and sends the result to next node in the reduction sequence.
- * Reduction Sequence: Reduce max data to X-Y Plane
- *   Reduce max data to Y Axis
- *   Reduce max data to origin.
- */
-
-
-#include <stdlib.h>
-#include "blue.h"
-
-#define A_SIZE 4
-
-#define X_DIM 3
-#define Y_DIM 3
-#define Z_DIM 3
-
-int REDUCE_HANDLER_ID;
-int COMPUTATION_ID;
-
-extern "C" void reduceHandler(char *);
-extern "C" void computeMax(char *);
-
-class ReductionMsg {
-public:
-  int max;
-};
-
-class ComputeMsg {
-public:
-  int dummy;
-};
-
-void BgEmulatorInit(int argc, char **argv)
-{
-  if (argc < 2) { 
-    CmiAbort("Usage: <program> <numCommTh> <numWorkTh>\n"); 
-  }
-
-  /* set machine configuration */
-  BgSetSize(X_DIM, Y_DIM, Z_DIM);
-  BgSetNumCommThread(atoi(argv[1]));
-  BgSetNumWorkThread(atoi(argv[2]));
-
-  REDUCE_HANDLER_ID = BgRegisterHandler(reduceHandler);
-  COMPUTATION_ID = BgRegisterHandler(computeMax);
-
-}
-
-void BgNodeStart(int argc, char **argv) {
-  int x, y, z;
-  BgGetXYZ(&x, &y, &z);
-
-  ComputeMsg *msg = new ComputeMsg;
-  BgSendLocalPacket(ANYTHREAD, COMPUTATION_ID, LARGE_WORK, 
-                       sizeof(ComputeMsg), (char *)msg);
-}
-
-void reduceHandler(char *info) {
-  // assumption: THey are initialized to zero?
-  static int max[X_DIM][Y_DIM][Z_DIM];
-  static int num_msg[X_DIM][Y_DIM][Z_DIM];
-
-  int i,j,k;
-  int external_max;
-
-  BgGetXYZ(&i,&j,&k);
-  external_max = ((ReductionMsg *)info)->max;
-  num_msg[i][j][k]++;
-
-  if ((i == 0) && (j == 0) && (k == 0)) {
-    // master node expects 4 messages:
-    // 1 from itself;
-    // 1 from the i dimension;
-    // 1 from the j dimension; and
-    // 1 from the k dimension
-    if (num_msg[i][j][k] < 4) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Can report max data after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      CmiPrintf("The maximal value is %d \n", max[i][j][k]);
-      BgShutdown();
-      return;
-    }
-  } else if ((i == 0) && (j == 0) && (k != Z_DIM - 1)) {
-    // nodes along the k-axis other than the last one expects 4 messages:
-    // 1 from itself;
-    // 1 from the i dimension;
-    // 1 from the j dimension; and
-    // 1 from the k dimension
-    if (num_msg[i][j][k] < 4) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Forwards max data to node i,j,k-1 after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      ReductionMsg *msg = new ReductionMsg;
-      msg->max = max[i][j][k];
-      BgSendPacket(i,j,k-1,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-    }
-  } else if ((i == 0) && (j == 0) && (k == Z_DIM - 1)) {
-    // the last node along the k-axis expects 3 messages:
-    // 1 from itself;
-    // 1 from the i dimension; and
-    // 1 from the j dimension
-    if (num_msg[i][j][k] < 3) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Forwards max data to node i,j,k-1 after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      ReductionMsg *msg = new ReductionMsg;
-      msg->max = max[i][j][k];
-      BgSendPacket(i,j,k-1,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-    }
-  } else if ((i == 0) && (j != Y_DIM - 1)) {
-    // for nodes along the j-k plane except for the last and first row of j,
-    // we expect 3 messages:
-    // 1 from itself;
-    // 1 from the i dimension; and
-    // 1 from the j dimension
-    if (num_msg[i][j][k] < 3) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Forwards max data to node i,j-1,k after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      ReductionMsg *msg = new ReductionMsg;
-      msg->max = max[i][j][k];
-      BgSendPacket(i,j-1,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-    }
-  } else if ((i == 0) && (j == Y_DIM - 1)) {
-    // for nodes along the last row of j on the j-k plane,
-    // we expect 2 messages:
-    // 1 from itself;
-    // 1 from the i dimension;
-    if (num_msg[i][j][k] < 2) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Forwards max data to node i,j-1,k after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      ReductionMsg *msg = new ReductionMsg;
-      msg->max = max[i][j][k];
-      BgSendPacket(i,j-1,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-    }
-  } else if (i != X_DIM - 1) {
-    // for nodes anywhere the last row of i,
-    // we expect 2 messages:
-    // 1 from itself;
-    // 1 from the i dimension;
-    if (num_msg[i][j][k] < 2) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Forwards max data to node i-1,j,k after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      ReductionMsg *msg = new ReductionMsg;
-      msg->max = max[i][j][k];
-      BgSendPacket(i-1,j,k,ANYTHREAD,REDUCE_HANDLER_ID,LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-    }
-  } else if (i == X_DIM - 1) {
-    // last row of i, we expect 1 message:
-    // 1 from itself;
-    if (num_msg[i][j][k] < 1) {
-      // not ready yet, so just find the max
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-    } else {
-      // done. Forwards max data to node i-1,j,k after making last comparison
-      if (max[i][j][k] < external_max) {
-       max[i][j][k] = external_max;
-      }
-      ReductionMsg *msg = new ReductionMsg;
-      msg->max = max[i][j][k];
-      BgSendPacket(i-1,j,k,-1,REDUCE_HANDLER_ID,LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-    }
-  }
-}
-
-void computeMax(char *info) {
-  int A[A_SIZE][A_SIZE];
-  int i, j;
-  int max = 0;
-
-  int x,y,z; // test variables
-  BgGetXYZ(&x,&y,&z);
-
-  // Initialize
-  for (i=0;i<A_SIZE;i++) {
-    for (j=0;j<A_SIZE;j++) {
-      A[i][j] = i*j;
-    }
-  }
-
-//  CmiPrintf("Finished Initializing %d %d %d!\n",  x , y , z);
-
-  // Find Max
-  for (i=0;i<A_SIZE;i++) {
-    for (j=0;j<A_SIZE;j++) {
-      if (max < A[i][j]) {
-       max = A[i][j];
-      }
-    }
-  }
-
-  // prepare to reduce
-  ReductionMsg *msg = new ReductionMsg;
-  msg->max = max;
-  BgSendLocalPacket(ANYTHREAD, REDUCE_HANDLER_ID, LARGE_WORK, 
-                               sizeof(ReductionMsg), (char *)msg);
-
-//  CmiPrintf("Sent reduce message to myself with max value %d\n", max);
-}
-
-
-\end{verbatim}
-
-\section{Compiling and Running}
-
-BlueGene Emulator now is integrated into Charm++ distribution as a runtime 
-library. Download Charm++ from Charm++ website and compile Charm++ and bluegene
-emulator by command "./build bluegene net-linux", change net-linux to whatever
-platform you are compiling on.
-
-Compile Blue Gene emulator programs using {\tt charmc} as one would
-in the case of compiling normal \charmpp{} programs. In order to link the
-Blue Gene library, specify \texttt{-language bluegene} as an argument
-to the {\tt charmc} linker.
+\input{install}
+\input{emulator}
 
 \input{index}
 \end{document}
+
+