examples/charm++: added an example showing the use of groups in a histogramming operation
authorPritish Jetley <pjetley2@illinois.edu>
Wed, 25 Jul 2012 18:59:23 +0000 (13:59 -0500)
committerPritish Jetley <pjetley2@illinois.edu>
Wed, 25 Jul 2012 18:59:28 +0000 (13:59 -0500)
examples/charm++/histogram_group/Makefile [new file with mode: 0644]
examples/charm++/histogram_group/pgm.cc [new file with mode: 0644]
examples/charm++/histogram_group/pgm.ci [new file with mode: 0644]

diff --git a/examples/charm++/histogram_group/Makefile b/examples/charm++/histogram_group/Makefile
new file mode 100644 (file)
index 0000000..c22c3be
--- /dev/null
@@ -0,0 +1,16 @@
+CHARMC =../../../bin/charmc $(OPTS)
+OPTS   = -O3 -g
+
+all: histogram
+
+histogram: pgm.o 
+       $(CHARMC) -language charm++ -o histogram pgm.o
+
+pgm.o: pgm.cc pgm.decl.h 
+       $(CHARMC) -o pgm.o pgm.cc
+
+pgm.decl.h: pgm.ci
+       $(CHARMC) pgm.ci
+
+clean:
+       rm -f *.decl.h *.def.h *.o histogram charmrun
diff --git a/examples/charm++/histogram_group/pgm.cc b/examples/charm++/histogram_group/pgm.cc
new file mode 100644 (file)
index 0000000..7526035
--- /dev/null
@@ -0,0 +1,136 @@
+#include "pgm.decl.h"
+#include <iostream>
+#include <cstdlib>
+#include <algorithm>
+
+CProxy_Main mainProxy;
+CProxy_Histogram histogramProxy;
+CProxy_HistogramMerger histogramMergerProxy;
+
+class Main : public CBase_Main {
+  int nChares;
+  int nElementsPerChare;
+  int maxElementValue;
+  int nBins;
+
+  public:
+  Main(CkArgMsg *m){
+    if(m->argc != 5){
+      CkPrintf("[main] Usage: pgm <nChares> <nElementsPerChare> <maxElementValue> <nBins>\n");
+      CkExit();
+    }
+
+    nChares = atoi(m->argv[1]);
+    nElementsPerChare = atoi(m->argv[2]);
+    maxElementValue = atoi(m->argv[3]);
+    nBins = atoi(m->argv[4]);
+
+    mainProxy = thisProxy;
+    histogramProxy = CProxy_Histogram::ckNew(nElementsPerChare, maxElementValue, nChares);
+    histogramMergerProxy = CProxy_HistogramMerger::ckNew(nBins);
+
+    histogramProxy.registerWithMerger(CkCallback(CkReductionTarget(Main, charesRegistered), mainProxy));
+  }
+
+  void charesRegistered(){
+    CkVec<int> bins(nBins);
+    int delta = maxElementValue/nBins;
+    if(nBins*delta < maxElementValue) delta++;
+
+    int currentKey = 0;
+
+    for(int i = 0; i < nBins; i++, currentKey += delta) bins[i] = currentKey;
+
+    histogramProxy.count(&bins[0], nBins);
+  }
+
+  void receiveHistogram(int *binCounts, int nBins){
+    int nTotalElements = 0;
+
+    CkPrintf("[main] histogram: \n");
+    for(int i = 0; i < nBins; i++){
+      CkPrintf("bin %d count %d\n", i, binCounts[i]);
+      nTotalElements += binCounts[i];
+    }
+
+    CkAssert(nTotalElements == nChares*nElementsPerChare);
+    CkExit();
+  }
+};
+
+class Histogram : public CBase_Histogram {
+  CkVec<int> myValues;
+
+  public:
+  Histogram(int nElementsPerChare, int maxElementValue){
+    myValues.resize(nElementsPerChare);
+    std::srand(thisIndex);
+
+    for(int i = 0; i < nElementsPerChare; i++){
+      myValues[i] = std::rand() % maxElementValue;
+    }
+  }
+
+  Histogram(CkMigrateMessage *m) {}
+
+  void registerWithMerger(const CkCallback &replyToCb);
+  void count(int *binKeys, int nKeys);
+};
+
+class HistogramMerger : public CBase_HistogramMerger {
+  int nCharesOnMyPe;
+  int nSubmissionsReceived;
+  CkVec<int> mergedCounts;
+
+  public:
+  HistogramMerger(int nKeys){
+    nCharesOnMyPe = 0;
+    nSubmissionsReceived = 0;
+
+    mergedCounts.resize(nKeys);
+    for(int i = 0; i < mergedCounts.size(); i++) mergedCounts[i] = 0;
+  }
+
+  void registerMe(){
+    nCharesOnMyPe++; 
+  }
+
+  void submitCounts(int *binCounts, int nBins){
+    CkAssert(nBins == mergedCounts.size());
+    for(int i = 0; i < nBins; i++) mergedCounts[i] += binCounts[i];
+
+    nSubmissionsReceived++;
+    if(nSubmissionsReceived == nCharesOnMyPe){
+      CkCallback cb(CkReductionTarget(Main, receiveHistogram), mainProxy);
+      contribute(mergedCounts.size()*sizeof(int), &mergedCounts[0], CkReduction::sum_int, cb);
+    }
+  }
+};
+
+void Histogram::registerWithMerger(const CkCallback &replyToCb){
+  histogramMergerProxy.ckLocalBranch()->registerMe();
+  contribute(replyToCb);
+}
+
+void Histogram::count(int *binKeys, int nKeys){
+  int *begin = binKeys;
+  int *end = begin + nKeys;
+  int *search = NULL;
+
+  CkVec<int> myCounts(nKeys);
+  for(int i = 0; i < nKeys; i++) myCounts[i] = 0;
+
+  for(int i = 0; i < myValues.size(); i++){
+    int value = myValues[i];
+    search = std::upper_bound(begin, end, value);
+
+    if(search != begin) search--; 
+    int bin = std::distance(begin, search);
+    myCounts[bin]++;
+  }
+
+  histogramMergerProxy.ckLocalBranch()->submitCounts(&myCounts[0], myCounts.size());
+}
+
+
+#include "pgm.def.h"
diff --git a/examples/charm++/histogram_group/pgm.ci b/examples/charm++/histogram_group/pgm.ci
new file mode 100644 (file)
index 0000000..9ac3b50
--- /dev/null
@@ -0,0 +1,31 @@
+mainmodule pgm {
+  readonly CProxy_Main mainProxy;
+  readonly CProxy_Histogram histogramProxy;
+  readonly CProxy_HistogramMerger histogramMergerProxy;
+
+  // Main chare sends a number of bins to Histogram chare array elements
+  mainchare Main {
+    entry Main(CkArgMsg *m);
+    entry [reductiontarget] void charesRegistered();
+    entry [reductiontarget] void receiveHistogram(int binCounts[nBins], int nBins);
+  };
+
+  // Each Histogram object has a set of values. When it receives a set of 
+  // bins, it counts the number of its values that lie within each bin. 
+  // Instead of directly contribute()ing counts to a reduction, these counts
+  // are submitted to the local branch of the HistogramMerger group.
+  array [1D] Histogram {
+    entry Histogram(int nElementsPerChare, int maxElementValue);
+    entry void registerWithMerger(const CkCallback &replyToCb);
+    entry [nokeep] void count(int binValues[nBins], int nBins);
+  };
+
+  // The local branch of this group on a PE receives count contributions from
+  // all the chare array elements on that PE. When it has received all the 
+  // contributions it is waiting for, it initiates a reduction to communicate
+  // the count results to the main chare.
+  group HistogramMerger {
+    entry HistogramMerger(int nKeys);
+  };
+
+};