Added a simple POSE program (examples/pose/PatternGen) to generate traffic patterns...
authorRyan Mokos <mokos@illinois.edu>
Wed, 3 Nov 2010 19:43:23 +0000 (14:43 -0500)
committerRyan Mokos <mokos@illinois.edu>
Wed, 3 Nov 2010 19:43:23 +0000 (14:43 -0500)
examples/pose/PatternGen/Makefile [new file with mode: 0644]
examples/pose/PatternGen/README [new file with mode: 0644]
examples/pose/PatternGen/Worker.C [new file with mode: 0644]
examples/pose/PatternGen/Worker.ci [new file with mode: 0644]
examples/pose/PatternGen/Worker.h [new file with mode: 0644]
examples/pose/PatternGen/defs.h [new file with mode: 0644]
examples/pose/PatternGen/pgm.C [new file with mode: 0644]
examples/pose/PatternGen/pgm.ci [new file with mode: 0644]
examples/pose/PatternGen/pgm.h [new file with mode: 0644]

diff --git a/examples/pose/PatternGen/Makefile b/examples/pose/PatternGen/Makefile
new file mode 100644 (file)
index 0000000..e7a7c33
--- /dev/null
@@ -0,0 +1,134 @@
+# NOTE: This is the basic Makefile template that includes the additional
+#       Makefile.simulation makefile that is found in the location of the
+#       current installation of POSE.
+#
+#      The Makefile.simulation set of rules allows the compilation of
+#       a SINGLE simulation module. If multiple simulation modules are
+#      desired, some "surgery" of Makefile.simulation (and this file)
+#      will be required. 
+#
+# ***********************************************************************
+
+# For parallel simulation
+OPTS=-g #-O #-DCMK_OPTIMIZE=1 -DCMK_MEMCHECKS_OFF=1
+ETRANS_OPTS=
+
+# For sequential simulation
+#OPTS=-O -DSEQUENTIAL_POSE=1 #-DCMK_OPTIMIZE=1 -DCMK_MEMCHECKS_OFF=1
+#ETRANS_OPTS=-s
+
+CHARMBASE=../../..
+CHARMBIN=$(CHARMBASE)/bin
+CHARMINC=$(CHARMBASE)/include
+
+CHARMC=$(CHARMBIN)/charmc -I$(CHARMINC)/pose $(OPTS)
+
+# Default Location variables
+# **************************
+#POSE_ROOT=$(HOME)/charm/net-linux/lib
+
+# Default module names
+# - MAKE MODIFICATIONS HERE
+# *************************
+PGM_MODULE=Pgm
+PGM=pgm
+OTHER=
+LIBS=-Lstdc++ -lm
+
+# Simulation object definitions 
+# *****************************
+SIM_OBJECTS=Worker_sim.o $(PGM).o 
+
+# EXECUTABLE GENERATION RULES 
+# - DO NOT MODIFY
+#****************************
+base:  $(PGM)
+       @echo "Simulation compiled."
+
+pure:   $(PGM).pure
+       @echo "Simulation (w purify) compiled."
+
+proj:   $(PGM).proj
+       @echo "Simulation (w projections log traces) compiled."
+
+summary:    $(PGM).summary
+       @echo "Simulation (w summary log traces) compiled."
+
+$(PGM):        $(SIM_OBJECTS) 
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM) \
+       -module pose -language charm++
+
+$(PGM).seq:    $(SIM_OBJECTS) 
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM).seq \
+       -module seqpose -language charm++
+
+$(PGM).alt:    $(SIM_OBJECTS) 
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM).alt \
+       -module pose -language charm++
+
+$(PGM).comm:   $(SIM_OBJECTS) 
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM).comm \
+       -lpose -language charm++ -module commlib
+
+$(PGM).pure:   $(SIM_OBJECTS)
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM).pure \
+       -lpose -language charm++ -purify
+
+$(PGM).proj:   $(SIM_OBJECTS)
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM).proj \
+       -module pose -language charm++ -tracemode projections
+
+$(PGM).summary:        $(SIM_OBJECTS)
+       $(CHARMC) $(SIM_OBJECTS) $(OTHER) $(LIBS) -o $(PGM).summary \
+       -lpose -language charm++ -tracemode summary
+
+# HOUSE-KEEPING RULES
+# - DO NOT MODIFY
+#********************
+
+# clean removes everything
+clean: clear rm_logs ;
+
+# clear removes only binaries and generated files
+clear:
+       rm -f charmrun conv-host *.o
+       rm -f *.def.h *.decl.h
+       rm -f $(PGM) $(PGM).pure $(PGM).proj $(PGM).summary
+       rm -f gmon.out #*#
+       rm -f core *~
+       rm -f TAGS *.headers
+       rm -f *_sim.*
+
+# rm_logs removes projections/summary log traces
+rm_logs:
+       rm -f [^j]*.log *.sum [^j]*.sts
+       rm -f *-bg.*.log *-bg.sts
+
+# SIMULATION COMPILATION RULES
+# - DO NOT MODIFY 
+#*****************************
+$(PGM).o :     $(PGM).C $(PGM).h $(PGM_MODULE).def.h $(PGM_MODULE).decl.h
+       $(CHARMC) -c -I$(CHARMINC) $(INCLUDES) $(LIBS) $(PGM).C
+
+$(PGM_MODULE).def.h $(PGM_MODULE).decl.h : $(PGM).ci
+       $(CHARMC) $(INCLUDES) $(LIBS) $(PGM).ci
+
+Worker_sim.o : Worker_sim.C Worker_sim.h Worker.def.h Worker.decl.h
+       $(CHARMC) -c $(LIBS) $(INCLUDES) -I$(CHARMINC) Worker_sim.C
+
+Worker.def.h Worker.decl.h : Worker_sim.ci
+       $(CHARMC) $(INCLUDES) $(LIBS) Worker_sim.ci
+
+Worker_sim.C Worker_sim.h Worker_sim.ci: Worker.C Worker.h Worker.ci 
+       $(CHARMBIN)/etrans.pl $(ETRANS_OPTS) Worker
+
+test: $(PGM)
+       ./pgm 20 200 MEDIUM -gm 10
+
+partest: $(PGM)
+       ./charmrun +p4 ./pgm 20 200 MEDIUM -gm 1
+       ./charmrun +p4 ./pgm +restart __pose_chkpt_files/
+
+seqtest: $(PGM).seq
+       ./pgm.seq 20 800 MEDIUM -gm 1
+       ./pgm.seq +restart __pose_chkpt_files/
diff --git a/examples/pose/PatternGen/README b/examples/pose/PatternGen/README
new file mode 100644 (file)
index 0000000..5925e20
--- /dev/null
@@ -0,0 +1,31 @@
+PatternGen
+----------
+This POSE application was created as a tool for generating simple traffic patterns.  It consists of an array of Worker posers that send and receive work messages.  The number of Workers and the specific pattern are choosen via command-line parameters.  The program is launched and the command-line parsed in pgm.C.  Worker.h and Worker.C define the Worker posers, and defs.h contains pattern constants and important #includes.
+
+
+Command line usage
+------------------
+
+./pgm <#workerObjs> <pattern#> [<pattern parameters>]
+
+In addition, running with -help lists the available patterns and usage:
+
+./pgm -help
+
+
+Steps for adding a pattern
+--------------------------
+1. Add new case statements to the switches in Worker::Worker, Worker::sendMessage, and Worker::recvMessage in Worker.C.
+2. If necessary, add any new helper functions or entry methods to Worker.h and Worker.C, making sure new entry methods are declared in Worker.ci.
+3. If necessary, add new event message classes to Worker.h and declare in Worker.ci.
+4. In defs.h, increment NUM_AVAILABLE_PATTERNS and add any new constants needed for the new pattern.
+5. If necessary, add parsing of new command-line parameters in main::main in pgm.C.
+6. Describe the new pattern briefly in the -help text in pgm.C, and provide more details below.
+
+
+Available patterns
+------------------
+Pattern 0: This is a simple ring pattern.  Worker 0 sends a message to Worker 1, Worker 1 sends to Worker 2 (once Worker 0's message is received), etc., until Worker N sends to Worker 0.  If only 1 Worker is created, it will keep sending to itself.  Constants in defs.h define how many messages are sent, the transit time for each message, and how much time is elapsed between receiving a message and sending the next.
+
+Pattern 1: In this pattern, each Worker begins by invoking its helper entry method, Worker::pattern1Iter.  This method sends one message to a Worker (via Worker::sendMessage) and then one message to itself with a short transit time (~200 GVT ticks) to initiate another send.  This repeats P1_MESSAGES_PER_ITER times (defined in defs.h).  This is then followed by sending a message to itself with a very long transit time (~1,000,000 GVT ticks).  This entire process is repeated for several iterations.  Note that there is no dependency between the recipt of a work message by Worker::recvMessage and when the next work message is sent--this is solely determined by the delay between the receipt of messages by Worker::pattern1Iter.
+
diff --git a/examples/pose/PatternGen/Worker.C b/examples/pose/PatternGen/Worker.C
new file mode 100644 (file)
index 0000000..6c98965
--- /dev/null
@@ -0,0 +1,115 @@
+#include "defs.h"
+
+/// Worker constructor
+Worker::Worker(WorkerInitMsg *initMsg) {
+  myPID = initMsg->myPID;
+  totalNumWorkers = initMsg->totalNumWorkers;
+  patternNum = initMsg->patternNum;
+  msgCount = 0;
+  iterNum = 0;
+  msgNum = 0;
+
+  dbPrintf("Worker %d constructed\n", myPID);
+
+  // send the first message(s) of the simulation
+  switch (patternNum) {
+  case 0:
+    if (myPID == 0) {
+      WorkMsg *wm = new WorkMsg(myPID, 0);
+      msgCount++;
+      POSE_invoke(recvMessage(wm), Worker, (totalNumWorkers > 1) ? 1 : 0, (POSE_TimeType)P0_MSG_TRANSIT_TIME);
+    }
+    break;
+  case 1: {
+    POSE_srand(time(NULL));
+    WorkMsg *wm = new WorkMsg(myPID, 0);
+    POSE_local_invoke(pattern1Iter(wm), 1);
+    break;
+  }
+  default:
+    CkPrintf("Invalid pattern number: %d\n", patternNum);
+    CkAbort("");
+    break;
+  }
+}
+
+/// Send a message to a Worker
+void Worker::sendMessage() {
+  dbPrintf("[ID=%d][ovt=%lld] sendMessage msgCount=%d iterNum=%d msgNum=%d\n", myPID, ovt, msgCount, iterNum, msgNum);
+
+  int destWorker;
+  POSE_TimeType msgTransitTime;
+  WorkMsg *wm;
+
+  // set message parameters based on the pattern
+  switch (patternNum) {
+  case 0:
+    destWorker = (myPID + 1) % totalNumWorkers;
+    msgTransitTime = (POSE_TimeType)P0_MSG_TRANSIT_TIME;
+    wm = new WorkMsg(myPID, msgCount);
+    msgCount++;
+    break;
+  case 1:
+    //destWorker = POSE_rand() % totalNumWorkers;
+    destWorker = myPID;
+    msgTransitTime = (POSE_TimeType)(P1_BASE_MSG_TRANSIT_TIME + (POSE_rand() % P1_MSG_TRANSIT_TIME_RANGE));
+    wm = new WorkMsg(myPID, msgCount);
+    msgCount++;
+    break;
+  default:
+    CkPrintf("Invalid pattern number: %d\n", patternNum);
+    CkAbort("");
+    break;
+  }
+
+  // send message
+  POSE_invoke(recvMessage(wm), Worker, destWorker, msgTransitTime);
+}
+
+/// ENTRY: Receive a message from a Worker
+void Worker::recvMessage(WorkMsg *wm) {
+  dbPrintf("[ID=%d][ovt=%lld] recvMessage msgCount=%d iterNum=%d msgNum=%d wm:[srcWorkerPID=%d msgID=%d]\n", 
+          myPID, ovt, msgCount, iterNum, msgNum, wm->srcWorkerPID, wm->msgID);
+
+  switch (patternNum) {
+  case 0:
+    elapse(P0_ELAPSE_TIME);
+    if (((wm->msgID * totalNumWorkers) + wm->srcWorkerPID) < (P0_MESSAGES_TO_SEND - 1)) {
+      sendMessage();
+    }
+    break;
+  case 1:
+    // do nothing; everything is done on the sending side
+    break;
+  default:
+    CkPrintf("Invalid pattern number: %d\n", patternNum);
+    CkAbort("");
+    break;
+  }
+}
+
+/// ENTRY: Send a message for pattern 1
+void Worker::pattern1Iter(WorkMsg *wm) {
+  dbPrintf("[ID=%d][ovt=%lld] pattern1Iter msgCount=%d iterNum=%d msgNum=%d\n", myPID, ovt, msgCount, iterNum, msgNum);
+
+  // For each iter, send P1_MESSAGES_PER_ITER messages and then wait a
+  // while before starting the next iter
+  if (iterNum < P1_ITERS) {
+    if (msgNum < P1_MESSAGES_PER_ITER) {
+      sendMessage();
+      WorkMsg *wm = new WorkMsg(myPID, -((iterNum * P1_MESSAGES_PER_ITER) + msgNum));
+      POSE_local_invoke(pattern1Iter(wm), P1_SHORT_DELAY);
+      msgNum++;
+    } else {
+      WorkMsg *wm = new WorkMsg(myPID, -((iterNum * P1_MESSAGES_PER_ITER) + msgNum));
+      POSE_local_invoke(pattern1Iter(wm), P1_LARGE_DELAY);
+      msgNum = 0;
+      iterNum++;
+    }
+  }
+}
+
+/// Termination function called at the end of the simulation
+void Worker::terminus() {
+  dbPrintf("[ID=%d] Simulation finished\n", myPID);
+}
diff --git a/examples/pose/PatternGen/Worker.ci b/examples/pose/PatternGen/Worker.ci
new file mode 100644 (file)
index 0000000..1946d66
--- /dev/null
@@ -0,0 +1,9 @@
+message WorkerInitMsg;
+message WorkMsg;
+
+poser Worker : sim adapt4 chpt {
+  entry Worker(WorkerInitMsg *);
+  // Event methods
+  entry [event] void recvMessage(WorkMsg *);
+  entry [event] void pattern1Iter(WorkMsg *);
+};
diff --git a/examples/pose/PatternGen/Worker.h b/examples/pose/PatternGen/Worker.h
new file mode 100644 (file)
index 0000000..f7f7c23
--- /dev/null
@@ -0,0 +1,96 @@
+#include "defs.h"
+
+/// Initialization message used for constructing a Worker
+class WorkerInitMsg {
+ public:
+  int myPID;           // poser ID
+  int totalNumWorkers; // number of worker objects in the simulation
+  int patternNum;      // communication pattern to use
+
+  WorkerInitMsg(int pid, int totalWorkers, int pattern): myPID(pid), totalNumWorkers(totalWorkers), patternNum(pattern) {}
+  WorkerInitMsg& operator=(const WorkerInitMsg& obj) {
+    eventMsg::operator=(obj);
+    myPID = obj.myPID;
+    totalNumWorkers = obj.totalNumWorkers;
+    patternNum = obj.patternNum;
+    return *this;
+  }
+};
+
+
+/// Message passed between Worker posers
+class WorkMsg {
+ public:
+  int srcWorkerPID; // poser ID of the source Worker
+  int msgID;        // ID of the message
+
+  WorkMsg(int workerPID, int id): srcWorkerPID(workerPID), msgID(id) {}
+  WorkMsg& operator=(const WorkMsg& obj) {
+    eventMsg::operator=(obj);
+    srcWorkerPID = obj.srcWorkerPID;
+    msgID = obj.msgID;
+    return *this;
+  }
+};
+
+
+/// Posers that send messages to each other
+class Worker {
+ public:
+  int myPID;           // poser ID
+  int totalNumWorkers; // number of worker objects in the simulation
+  int patternNum;      // communication pattern to use
+  int msgCount;        // current message count (total for whole simulation)
+  int iterNum;         // current iteration number
+  int msgNum;          // current message number (for current iteration)
+
+  Worker() {}
+  Worker(WorkerInitMsg *m); 
+  ~Worker() {}
+  Worker& operator=(const Worker& obj) {
+    rep::operator=(obj);
+    myPID = obj.myPID;
+    totalNumWorkers = obj.totalNumWorkers;
+    patternNum = obj.patternNum;
+    msgCount = obj.msgCount;
+    iterNum = obj.iterNum;
+    msgNum = obj.msgNum;
+    return *this;
+  }
+  void pup(PUP::er &p) { 
+    chpt<state_Worker>::pup(p); 
+    p|myPID; p|totalNumWorkers; p|patternNum; 
+    p|msgCount; p|iterNum; p|msgNum;
+  }
+  void dump() {
+    CkPrintf("Worker: myPID=%d totalNumWorkers=%d patternNum=%d msgCount=%d iterNum=%d msgNum=%d\n", 
+            myPID, totalNumWorkers, patternNum, msgCount, iterNum, msgNum);
+    chpt<state_Worker>::dump();
+  }
+  void terminus();
+
+  /// Send a message to a Worker
+  void sendMessage();
+
+  /// ENTRY: Receive a message from a Worker
+  void recvMessage(WorkMsg *wm);
+  void recvMessage_anti(WorkMsg *wm) {
+    dbPrintf("[ID=%d][ovt=%lld] recvMessage_anti msgCount=%d iterNum=%d msgNum=%d\n", myPID, ovt, msgCount, iterNum, msgNum);
+    restore(this);
+    dbPrintf("   ovt after rollback=%lld\n", ovt);
+  }
+  void recvMessage_commit(WorkMsg *wm) {
+    dbPrintf("[ID=%d][ovt=%lld] recvMessage_commit msgCount=%d iterNum=%d msgNum=%d\n", myPID, ovt, msgCount, iterNum, msgNum);
+  }
+
+  /// ENTRY: Send a message for pattern 1
+  void pattern1Iter(WorkMsg *wm);
+  void pattern1Iter_anti(WorkMsg *wm) {
+    dbPrintf("[ID=%d][ovt=%lld] pattern1Iter_anti msgCount=%d iterNum=%d msgNum=%d\n", myPID, ovt, msgCount, iterNum, msgNum);
+    restore(this);
+    dbPrintf("   ovt after rollback=%lld\n", ovt);
+  }
+  void pattern1Iter_commit(WorkMsg *wm) {
+    dbPrintf("[ID=%d][ovt=%lld] pattern1Iter_commit msgCount=%d iterNum=%d msgNum=%d\n", myPID, ovt, msgCount, iterNum, msgNum);
+  }
+};
diff --git a/examples/pose/PatternGen/defs.h b/examples/pose/PatternGen/defs.h
new file mode 100644 (file)
index 0000000..a7cde60
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef _DEFS_H
+#define _DEFS_H
+
+#include <unistd.h>
+#include <math.h>
+#include <time.h>
+
+#define NUM_AVAILABLE_PATTERNS 2
+
+// set to "if (1) CkPrintf" to turn on debug print statements
+#define dbPrintf if (0) CkPrintf
+
+// for pattern 0
+#define P0_MESSAGES_TO_SEND 20
+#define P0_MSG_TRANSIT_TIME 100
+#define P0_ELAPSE_TIME 50
+
+// for pattern 1
+#define P1_BASE_MSG_TRANSIT_TIME 80
+#define P1_MSG_TRANSIT_TIME_RANGE 41  // gives range of 0-40
+#define P1_ITERS 3
+#define P1_MESSAGES_PER_ITER 5
+#define P1_SHORT_DELAY 200
+#define P1_LARGE_DELAY 1000000
+
+#endif  // _DEFS_H
diff --git a/examples/pose/PatternGen/pgm.C b/examples/pose/PatternGen/pgm.C
new file mode 100644 (file)
index 0000000..83f6667
--- /dev/null
@@ -0,0 +1,48 @@
+#include "pose.h"
+#include "pgm.h"
+#include "Pgm.def.h"
+#include "Worker_sim.h"
+
+main::main(CkArgMsg *m) { 
+  CkGetChareID(&mainhandle);
+
+  int numWorkers, patternNum;
+
+  if ((m->argc < 3) || (strcmp(m->argv[1], "-help") == 0)) {
+    CkPrintf("Usage: pgm <#workerObjs> <pattern#> [<pattern parameters>]\n");
+    CkPrintf("\n");
+    CkPrintf("Pattern 0: Simple ring test\n");
+    CkPrintf("   Pattern parameters: none\n");
+    CkPrintf("Pattern 1: Short communcation bursts (~100 GVT ticks apart), long message send (~1M ticks), repeat\n");
+    CkPrintf("   Pattern parameters: none\n");
+    CkExit();
+  }
+
+  numWorkers = atoi(m->argv[1]);
+  if (numWorkers < 1) {
+    CkPrintf("Number of Worker objects (%d) must be positive\n", numWorkers);
+    CkExit();
+  }
+
+  patternNum = atoi(m->argv[2]);
+  if ((patternNum < 0) || (patternNum >= NUM_AVAILABLE_PATTERNS)) {
+    CkPrintf("Invalid pattern number: %d\n", patternNum);
+    CkPrintf("Options: 0-%d\n", NUM_AVAILABLE_PATTERNS - 1);
+    CkExit();
+  }
+
+  CkPrintf("Pattern %d selected with %d Worker objects spread across %d PE(s)\n", patternNum, numWorkers, CkNumPes());
+
+  POSE_init();
+
+  int mappedPE;
+  WorkerInitMsg *initMsg;
+  for (int workerNum = 0; workerNum < numWorkers; workerNum++) {
+    initMsg = new WorkerInitMsg(workerNum, numWorkers, patternNum);
+    initMsg->Timestamp(0);
+    mappedPE = workerNum % CkNumPes();
+    dbPrintf("Placing Worker %d on PE %d\n", workerNum, mappedPE);
+    (*(CProxy_Worker *) &POSE_Objects)[workerNum].insert(initMsg, mappedPE);
+  }
+  POSE_Objects.doneInserting();
+}
diff --git a/examples/pose/PatternGen/pgm.ci b/examples/pose/PatternGen/pgm.ci
new file mode 100644 (file)
index 0000000..d4c199c
--- /dev/null
@@ -0,0 +1,8 @@
+mainmodule Pgm {
+  extern module Worker;
+  readonly CkChareID mainhandle;
+  
+  mainchare main {
+    entry main();
+  };
+};
diff --git a/examples/pose/PatternGen/pgm.h b/examples/pose/PatternGen/pgm.h
new file mode 100644 (file)
index 0000000..2d5cf8c
--- /dev/null
@@ -0,0 +1,9 @@
+#include "Pgm.decl.h"
+
+CkChareID mainhandle;
+
+class main : public Chare {
+public:
+  main(CkArgMsg *m);
+  main(CkMigrateMessage *) {};
+};