Zcpy Bcast Sender-side API: Add a large buffer bcast benchmark 16/3816/36
authorNitin Bhat <nbhat4@illinois.edu>
Tue, 2 Oct 2018 18:26:03 +0000 (14:26 -0400)
committerEvan Ramos <evan@hpccharm.com>
Wed, 10 Apr 2019 18:03:55 +0000 (13:03 -0500)
Co-authored-by: Evan Ramos <evan@hpccharm.com>
Change-Id: I33190301d75e27623281cd40556b45ae8e9f8c1b

tests/charm++/zerocopy/Makefile
tests/charm++/zerocopy/largedata/Makefile [new file with mode: 0644]
tests/charm++/zerocopy/largedata/largedata.C [new file with mode: 0644]
tests/charm++/zerocopy/largedata/largedata.ci [new file with mode: 0644]

index 0e9f74034248db043cf8083687d54ac539e99a8f..6d994926727760490439c2ca5d5ae805e04166e1 100644 (file)
@@ -1,4 +1,5 @@
 DIRS = \
+  largedata \
   zerocopy_with_qd \
 
 TESTDIRS = $(DIRS)
diff --git a/tests/charm++/zerocopy/largedata/Makefile b/tests/charm++/zerocopy/largedata/Makefile
new file mode 100644 (file)
index 0000000..6592dcc
--- /dev/null
@@ -0,0 +1,35 @@
+-include ../../../common.mk
+SRC=../../../../src
+CHARMC=../../../../bin/charmc $(OPTS)
+
+NAME = largedata
+
+OBJS = $(NAME).o
+
+all: pgm
+
+pgm: $(OBJS)
+       $(CHARMC) -language charm++ -o pgm $(OBJS)
+
+pgm.prj: $(OBJS)
+       $(CHARMC) -tracemode projections -language charm++ -o pgm.prj $(OBJS)
+
+cifiles: $(NAME).ci
+       $(CHARMC) $(NAME).ci
+       touch cifiles
+
+clean:
+       rm -f *.decl.h *.def.h conv-host *.o pgm charmrun cifiles pgm.exe pgm.pdb pgm.ilk
+
+$(NAME).o: $(NAME).C cifiles
+       $(CHARMC) -I$(SRC)/conv-core $<
+
+test: all
+       $(call run, ./pgm +p4 200000 10)
+       $(call run, ./pgm +p6 200000 10)
+
+test-bench: all
+       $(call run, ./pgm +p10)
+
+bgtest: all
+       $(call run, ./pgm +p2 +x2 +y1 +z1 )
diff --git a/tests/charm++/zerocopy/largedata/largedata.C b/tests/charm++/zerocopy/largedata/largedata.C
new file mode 100644 (file)
index 0000000..3b8938c
--- /dev/null
@@ -0,0 +1,154 @@
+#include <string.h> // for strlen, and strcmp
+#include <charm++.h>
+
+#include "largedata.decl.h"
+
+#define NITER 100
+#define PAYLOAD (1ull<<30ull)
+
+CProxy_main mainProxy;
+int iterations;
+size_t payload;
+
+#define DEBUG(x) //x
+
+class main : public CBase_main
+{
+  int niter, counter;
+  char *buffer;
+  CProxy_LargeDataNodeGroup ngid;
+  double start_time, end_time, total_time;
+  CkCallback cb;
+
+public:
+  main(CkMigrateMessage *m) {}
+  main(CkArgMsg* m)
+  {
+    iterations = NITER;
+    payload = PAYLOAD;
+    if(m->argc>1)
+      payload=atoi(m->argv[1]);
+    if(m->argc>2)
+      iterations=atoi(m->argv[2]);
+    if(m->argc>3) {
+      CkPrintf("Usage: pgm +p2 [payload] [iterations]\n Where payload (default %zd) is integer >0, iterations (default %d) is integer >0\n", (size_t)PAYLOAD, NITER);
+      CmiAbort("Incorrect arguments\n");
+    }
+    CkPrintf("Large data transfer with payload: %zd iterations: %d\n", payload, iterations);
+    delete m;
+
+    // Initialize
+    niter = 0;
+    counter = 0;
+    total_time = 0;
+    mainProxy = thisProxy;
+
+    // Allocate a buffer to send
+    buffer = new char[payload];
+
+    // Create a nodegroup
+    ngid = CProxy_LargeDataNodeGroup::ckNew(iterations);
+
+    // Create a callback method to pass in the Zerocopy Bcast API call
+    int idx_zerocopySent = CkIndex_main::zerocopySent(NULL);
+    cb = CkCallback(idx_zerocopySent, thisProxy);
+
+    // Regular Bcast API's warmup run, which is untimed
+    ngid.recv(buffer, payload);
+  }
+
+  // Invoked on main after a reduction by all the nodegroup elements
+  void regular_bcast_done() {
+    niter++; // An iteration of the Regular Bcast API is complete
+
+    DEBUG(CkPrintf("[%d][%d][%d] Iteration %d: Regular Bcast API reduction complete, data received by all nodegroup elements\n", CkMyPe(), CkMyNode(), CmiMyRank(), niter);)
+
+    if(niter != 1) {  // For all runs excluding the warmup run
+      end_time = CkWallTimer();
+      total_time += end_time - start_time;
+
+      if(niter == iterations + 1) {   // 1 is added for the warmup run
+        // All iterations have been completed;
+        // print result
+        CkPrintf("[%d][%d][%d] Regular API sending complete, Time taken per iteration after %d iterations is: %lf us\n", CkMyPe(), CkMyNode(), CmiMyRank(), iterations, 1.0e6*total_time/iterations);
+
+        // Initialize
+        niter = 0;
+        total_time = 0;
+
+        // Zerocopy Bcast API's warmup run, which is untimed
+        ngid.recv_zerocopy(CkSendBuffer(buffer, cb), payload);
+        return;
+      }
+    }
+    start_time = CkWallTimer();
+    ngid.recv(buffer, payload); // regular API's non-warmup run
+  }
+
+
+
+
+  void zerocopySent(CkDataMsg *msg) {
+    niter++; // An iteration of the Zerocopy Bcast API is complete
+
+    DEBUG(CkPrintf("[%d][%d][%d] Iteration %d: Zerocopy Bcast API callback invocation complete, data received by all nodegroup elements\n", CkMyPe(), CkMyNode(), CmiMyRank(), niter);)
+
+    if(niter != 1) {  // For all runs excluding the warmup run
+      end_time = CkWallTimer();
+      total_time += end_time - start_time;
+
+      if(niter == iterations + 1) {   // 1 is added for the warmup run
+        // All iterations have been completed;
+        // print result
+        CkPrintf("[%d][%d][%d] Bcast API sending complete, Time taken per iteration after %d iterations is: %lf us\n", CkMyPe(), CkMyNode(), CmiMyRank(), iterations, 1.0e6*total_time/iterations);
+        done();
+        return;
+      }
+    }
+
+    start_time = CkWallTimer();
+    ngid.recv_zerocopy(CkSendBuffer(buffer, cb), payload);
+  }
+
+  void done() {
+    counter++;
+    if(counter == CkNumNodes() + 1) {  // 1 is added for the done call from the callback
+      CkPrintf("[%d][%d][%d] All recipients have received the data\n", CkMyPe(), CkMyNode(), CmiMyRank());
+      CkExit();
+    }
+  }
+};
+
+
+class LargeDataNodeGroup : public CBase_LargeDataNodeGroup
+{
+  int niter, iterations;
+  CkCallback regCb;
+
+public:
+  LargeDataNodeGroup(int _iterations) {
+    niter = 0;
+    iterations = _iterations;
+    regCb = CkCallback(CkReductionTarget(main, regular_bcast_done), mainProxy);
+  }
+
+  void recv(char *msg, size_t size) {
+    niter++;
+    DEBUG(CkPrintf("[%d][%d][%d] Iteration %d: Received data through regular API\n", CkMyPe(), CkMyNode(), CmiMyRank(), niter);)
+    if(niter == iterations + 1) { // 1 is added for the warmup run
+      niter = 0; // Reset the value of niter as regular API is complete
+    }
+    contribute(regCb); // Nodegroup reduction to signal completion to the main chare
+  }
+
+  void recv_zerocopy(char *msg, size_t size) {
+    niter++;
+    DEBUG(CkPrintf("[%d][%d][%d] Iteration %d: Received data through zerocopy API\n", CkMyPe(), CkMyNode(), CmiMyRank(), niter);)
+    if(niter == iterations + 1) { // 1 is added for the warmup run
+      mainProxy.done(); // Signal mainchare to indicate that data has successfully been received
+    }
+  }
+};
+
+
+#include "largedata.def.h"
diff --git a/tests/charm++/zerocopy/largedata/largedata.ci b/tests/charm++/zerocopy/largedata/largedata.ci
new file mode 100644 (file)
index 0000000..391cfde
--- /dev/null
@@ -0,0 +1,25 @@
+mainmodule largedata
+{
+  readonly CProxy_main mainProxy;
+  readonly int iterations;
+  readonly size_t payload;
+
+  mainchare main
+  {
+    entry main(CkArgMsg *);
+    entry [reductiontarget] void regular_bcast_done();
+    entry void zerocopySent(CkDataMsg *msg);
+    entry void done();
+  }
+
+  nodegroup LargeDataNodeGroup
+  {
+    entry LargeDataNodeGroup(int iterations);
+
+    // regular message send api
+    entry [exclusive] void recv(char msg[size], size_t size);
+
+    // charm++ zero copy message send api for parameters marked "nocopy"
+    entry [exclusive] void recv_zerocopy(nocopy char msg[size], size_t size);
+  }
+}