ZC Bcast APIs: Add a benchmark to compare bcast APIs 60/4960/31
authorNitin Bhat <nbhat4@illinois.edu>
Tue, 19 Feb 2019 15:07:02 +0000 (09:07 -0600)
committerNitin Bhat <nbhat4@illinois.edu>
Wed, 24 Apr 2019 21:03:08 +0000 (16:03 -0500)
Change-Id: I8310c89e5e26fa6e49040029d488794226ad889c

examples/charm++/zerocopy/benchmarks/Makefile
examples/charm++/zerocopy/benchmarks/bcastPingAll/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/benchmarks/bcastPingAll/ping_all.C [new file with mode: 0644]
examples/charm++/zerocopy/benchmarks/bcastPingAll/ping_all.ci [new file with mode: 0644]

index 29b4b7b2b8f05c5e3446353bd21e5059a1230294..e6cfcbe5244f6144b1d62b2898730a6abb7c5e2d 100644 (file)
@@ -1,5 +1,6 @@
 DIRS = \
   p2pPingpong \
+  bcastPingAll \
 
 TESTDIRS = $(DIRS)
 
diff --git a/examples/charm++/zerocopy/benchmarks/bcastPingAll/Makefile b/examples/charm++/zerocopy/benchmarks/bcastPingAll/Makefile
new file mode 100644 (file)
index 0000000..ab646a0
--- /dev/null
@@ -0,0 +1,27 @@
+-include ../../../../common.mk
+CHARMC=../../../../../bin/charmc $(OPTS)
+
+all:   ping_all
+
+OBJS = ping_all.o
+
+ping_all: $(OBJS)
+       $(CHARMC) -language charm++ -o ping_all $(OBJS)
+
+cifiles: ping_all.ci
+       $(CHARMC)  ping_all.ci
+       touch cifiles
+
+ping_all.o: ping_all.C cifiles
+       $(CHARMC) -c ping_all.C
+
+test: all
+       $(call run, +p1 ./ping_all 1024 8192 2 1 1)
+       $(call run, +p2 ./ping_all 1024 8192 2 1 1)
+
+test-bench: all
+       $(call run, ./ping_all +p1)
+       $(call run, ./ping_all +p2)
+
+clean:
+       rm -f *.decl.h *.def.h conv-host *.o ping_all charmrun cifiles
diff --git a/examples/charm++/zerocopy/benchmarks/bcastPingAll/ping_all.C b/examples/charm++/zerocopy/benchmarks/bcastPingAll/ping_all.C
new file mode 100644 (file)
index 0000000..7a1c641
--- /dev/null
@@ -0,0 +1,391 @@
+#include <string.h> // for strlen, and strcmp
+
+#include <charm++.h>
+
+#include "ping_all.decl.h"
+
+CProxy_main mainProxy;
+int printFormat;
+
+#define DEBUG(x) //x
+
+class main : public CBase_main
+{
+  int niter, send_counter, recv_counter, iterations;
+  size_t minSize, maxSize, smallIter, bigIter;
+  char *buffer, *regBuffer;
+  CProxy_LargeDataNodeGroup ngid;
+  double start_time, end_time, reg_time1, zcpy_send_time1, zcpy_send_time2, zcpy_send_time3;
+  double reg_time2, zcpy_send_with_copy_time, zcpy_recv_time1, zcpy_recv_time2, zcpy_recv_time3;
+  CkCallback doneCb;
+  size_t size;
+  bool warmUp;
+  int zc_current_operation;
+
+public:
+  main(CkMigrateMessage *m) {}
+  main(CkArgMsg* m)
+  {
+    if(m->argc == 6) {
+      minSize = atoi(m->argv[1])/2; // Start with a smaller size to run a warm up phase
+      maxSize = atoi(m->argv[2]);
+      smallIter = atoi(m->argv[3]);
+      bigIter = atoi(m->argv[4]);
+      printFormat = atoi(m->argv[5]);
+    } else if(m->argc == 1) {
+      // use defaults
+      minSize = 16; // Start with a smaller size to run a warm up phase before starting message size at 1024 bytes
+      maxSize = 1 << 25;
+      smallIter = 100;
+      bigIter = 10;
+      printFormat = 0;
+    } else {
+      CkPrintf("Usage: ./ping_all <min size> <max size> <small message iter> <big message iter> <print format (0 for csv, 1 for regular)\n");
+      CkExit(1);
+    }
+    if(printFormat != 0 && printFormat != 1) {
+      CkPrintf("<print format> cannot be a value other than 0 or 1 (0 for csv, 1 for regular)\n");
+      CkExit(1);
+    }
+    delete m;
+    // Initialize
+    size = minSize;
+    niter = 0;
+    send_counter = 0;
+    recv_counter = 0;
+    mainProxy = thisProxy;
+    warmUp = true;
+    iterations = smallIter;
+    zc_current_operation = 1;
+
+    // Allocate a buffer to send
+    buffer = new char[maxSize];
+
+    // Allocate another buffer from pre-registered memory to send
+    regBuffer = (char *)CkRdmaAlloc(sizeof(char) * maxSize);
+
+    // Create a nodegroup
+    ngid = CProxy_LargeDataNodeGroup::ckNew(maxSize);
+
+    int idx_zerocopySendDone = CkIndex_main::recv_zc_send_free_ptr(NULL);
+    doneCb = CkCallback(idx_zerocopySendDone, thisProxy);
+
+    if(printFormat == 0) // csv print format
+      CkPrintf("Size (Bytes),Iterations,Regular Bcast(us),ZC EM Bcast Send UNREG mode(us),ZC EM Bcast Send REG Mode (us),ZC EM Bcast Send PREREG Mode(us),Regular Bcast with Copy(us),ZC EM Bcast Send with Copy(us),ZC Bcast Post UNREG(us),ZC Bcast Post REG(us),ZC Bcast Post PREREG(us)\n");
+    else // regular print format
+      CkPrintf("Size (Bytes)\t\tIterations\t||\tRegular Bcast(us)\tZC EM Bcast 1(us)\tZC EM Bcast 2(us)\tZC EM Bcast 2(us)\t||\tRegular Bcast & Copy(us)\tZC EM Bcast Send & Copy(us)\tZC Bcast Post 1(us)\tZC Bcast Post 2(us)\tZC Bcast Post 3(us)\n");
+    CkStartQD(CkCallback(CkIndex_main::start(), mainProxy));
+  }
+
+  void start() {
+    if(size >= 1 << 19)
+      iterations = bigIter;
+    else
+      iterations = smallIter;
+
+    if(size < minSize) {
+      // warmUp phase
+      start_time = CkWallTimer();
+      ngid.recv(buffer, size, niter, warmUp, iterations);
+    } else if(size <= maxSize) {
+      // regular experiment phase
+      start_time = CkWallTimer();
+      ngid.recv(buffer, size, niter, warmUp, iterations);
+    } else {
+      // completion phase
+      done();
+    }
+  }
+
+  void recv_zc_send_free_ptr(CkDataMsg *msg) {
+    switch(zc_current_operation) {
+      case 1:   recv_zc_send_done1();
+                break;
+      case 2:   recv_zc_send_done2();
+                break;
+      case 3:   recv_zc_send_done3();
+                break;
+      case 4:   recv_zc_send_with_copy_done();
+                break;
+      case 5:   recv_zc_post_done1();
+                break;
+      case 6:   recv_zc_post_done2();
+                break;
+      case 7:   recv_zc_post_done3();
+                break;
+      default:  CmiAbort("Incorrect mode\n");
+                break;
+    }
+  }
+
+
+
+  // Invoked on main after a reduction by all the nodegroup elements
+  void recv_done() {
+    niter++; // An iteration of the Regular Bcast API is complete
+    if(niter == iterations) {
+      end_time = CkWallTimer();
+      reg_time1 = 1.0e6*(end_time - start_time)/iterations;
+      niter = 0;
+      zc_current_operation = 1;
+      start_time = CkWallTimer();
+      ngid.recv_zc_send1(CkSendBuffer(buffer, doneCb, CK_BUFFER_UNREG), size, niter, warmUp, iterations);
+    } else {
+      ngid.recv(buffer, size, niter, warmUp, iterations);
+    }
+  }
+
+  void recv_zc_send_done1() {
+    send_counter++;
+    if(send_counter == 2) {
+      send_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Send API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_send_time1 = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+        zc_current_operation = 2;
+        start_time = CkWallTimer();
+        ngid.recv_zc_send2(CkSendBuffer(buffer, doneCb, CK_BUFFER_REG), size, niter, warmUp, iterations);
+      } else {
+        ngid.recv_zc_send1(CkSendBuffer(buffer, doneCb, CK_BUFFER_UNREG), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void recv_zc_send_done2() {
+    send_counter++;
+    if(send_counter == 2) {
+      send_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Send API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_send_time2 = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+        zc_current_operation = 3;
+        start_time = CkWallTimer();
+        ngid.recv_zc_send3(CkSendBuffer(regBuffer, doneCb, CK_BUFFER_PREREG), size, niter, warmUp, iterations);
+      } else {
+        ngid.recv_zc_send2(CkSendBuffer(buffer, doneCb, CK_BUFFER_REG), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void recv_zc_send_done3() {
+    send_counter++;
+    if(send_counter == 2) {
+      send_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Send API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_send_time3 = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+        start_time = CkWallTimer();
+        ngid.recv_with_copy(buffer, size, niter, warmUp, iterations);
+      } else {
+        ngid.recv_zc_send3(CkSendBuffer(regBuffer, doneCb, CK_BUFFER_PREREG), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void recv_with_copy_done() {
+    niter++; // An iteration of the Regular Bcast API is complete
+    if(niter == iterations) {
+      end_time = CkWallTimer();
+      reg_time2 = 1.0e6*(end_time - start_time)/iterations;
+      niter = 0;
+      zc_current_operation = 4;
+      start_time = CkWallTimer();
+      ngid.recv_zc_send_with_copy(CkSendBuffer(buffer, doneCb), size, niter, warmUp, iterations);
+    } else {
+      ngid.recv_with_copy(buffer, size, niter, warmUp, iterations);
+    }
+  }
+
+  void recv_zc_send_with_copy_done() {
+    send_counter++;
+    if(send_counter == 2) {
+      send_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Send API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_send_with_copy_time = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+        zc_current_operation = 5;
+        start_time = CkWallTimer();
+        ngid.recv_zc_post1(CkSendBuffer(buffer, doneCb, CK_BUFFER_UNREG), size, niter, warmUp, iterations);
+      } else {
+        ngid.recv_zc_send_with_copy(CkSendBuffer(buffer, doneCb), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void recv_zc_post_done1() {
+    recv_counter++;
+    if(recv_counter == 2) {
+      recv_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Recv API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_recv_time1 = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+        zc_current_operation = 6;
+        start_time = CkWallTimer();
+        ngid.recv_zc_post2(CkSendBuffer(buffer, doneCb, CK_BUFFER_REG), size, niter, warmUp, iterations);
+      } else {
+        ngid.recv_zc_post1(CkSendBuffer(buffer, doneCb, CK_BUFFER_UNREG), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void recv_zc_post_done2() {
+    recv_counter++;
+    if(recv_counter == 2) {
+      recv_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Recv API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_recv_time2 = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+        zc_current_operation = 7;
+        start_time = CkWallTimer();
+        ngid.recv_zc_post3(CkSendBuffer(regBuffer, doneCb, CK_BUFFER_PREREG), size, niter, warmUp, iterations);
+      } else {
+        ngid.recv_zc_post2(CkSendBuffer(buffer, doneCb, CK_BUFFER_REG), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void recv_zc_post_done3() {
+    recv_counter++;
+    if(recv_counter == 2) {
+      recv_counter = 0;
+      niter++; // An iteration of the Zerocopy Bcast Recv API is complete
+      if(niter == iterations) {
+        end_time = CkWallTimer();
+        zcpy_recv_time3 = 1.0e6*(end_time - start_time)/iterations;
+        niter = 0;
+
+        if(warmUp == false) {
+          if(printFormat == 0) // csv print format
+            CkPrintf("%d,%d,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf\n",size, iterations, reg_time1, zcpy_send_time1, zcpy_send_time2, zcpy_send_time3, reg_time2, zcpy_send_with_copy_time, zcpy_recv_time1, zcpy_recv_time2, zcpy_recv_time3);
+          else { // regular print format
+            if(size < 1 << 24)
+              CkPrintf("%d\t\t\t%d\t\t||\t%lf\t\t%lf\t\t%lf\t\t%lf\t\t||\t%lf\t\t\t%lf\t\t\t%lf\t\t%lf\t\t%lf\n", size, iterations, reg_time1, zcpy_send_time1, zcpy_send_time2, zcpy_send_time3, reg_time2, zcpy_send_with_copy_time, zcpy_recv_time1, zcpy_recv_time2, zcpy_recv_time3);
+            else
+              CkPrintf("%d\t\t%d\t\t||\t%lf\t\t%lf\t\t%lf\t\t%lf\t\t||\t%lf\t\t\t%lf\t\t\t%lf\t\t%lf\t\t%lf\n", size, iterations, reg_time1, zcpy_send_time1, zcpy_send_time2, zcpy_send_time3, reg_time2, zcpy_send_with_copy_time, zcpy_recv_time1, zcpy_recv_time2, zcpy_recv_time3);
+          }
+        }
+        size = size << 1;
+        if(warmUp)
+          done();
+        else
+          mainProxy.start();
+      } else {
+        ngid.recv_zc_post3(CkSendBuffer(regBuffer, doneCb, CK_BUFFER_PREREG), size, niter, warmUp, iterations);
+      }
+    }
+  }
+
+  void done() {
+    if(warmUp) {
+      // warmUp phase complete
+      warmUp = false;
+      mainProxy.start();
+    } else {
+      // experiment complete
+      CkExit();
+    }
+  }
+};
+
+
+class LargeDataNodeGroup : public CBase_LargeDataNodeGroup {
+
+  CkCallback regCb1, zcSendCb1, zcSendCb2, zcSendCb3;
+  CkCallback regCb2, zcSendWithCopyCb, zcRecvCb1, zcRecvCb2, zcRecvCb3;
+  char *myBuffer, *regBuffer;
+
+public:
+  LargeDataNodeGroup(int maxSize) {
+
+    regCb1 = CkCallback(CkReductionTarget(main, recv_done), mainProxy);
+
+    zcSendCb1 = CkCallback(CkReductionTarget(main, recv_zc_send_done1), mainProxy);
+    zcSendCb2 = CkCallback(CkReductionTarget(main, recv_zc_send_done2), mainProxy);
+    zcSendCb3 = CkCallback(CkReductionTarget(main, recv_zc_send_done3), mainProxy);
+
+    regCb2 = CkCallback(CkReductionTarget(main, recv_with_copy_done), mainProxy);
+
+    zcSendWithCopyCb = CkCallback(CkReductionTarget(main, recv_zc_send_with_copy_done), mainProxy);
+
+    zcRecvCb1 = CkCallback(CkReductionTarget(main, recv_zc_post_done1), mainProxy);
+    zcRecvCb2 = CkCallback(CkReductionTarget(main, recv_zc_post_done2), mainProxy);
+    zcRecvCb3 = CkCallback(CkReductionTarget(main, recv_zc_post_done3), mainProxy);
+
+    // allocate a large buffer to receive the sent buffer
+    myBuffer = new char[maxSize];
+
+    // Allocate another buffer from pre-registered memory to receive the sent buffer
+    regBuffer = (char *)CkRdmaAlloc(sizeof(char) * maxSize);
+  }
+
+  void recv(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(regCb1); // Nodegroup reduction to signal completion to the main chare
+  }
+
+  void recv_zc_send1(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(zcSendCb1);
+  }
+
+  void recv_zc_send2(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(zcSendCb2);
+  }
+
+  void recv_zc_send3(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(zcSendCb3);
+  }
+
+  void recv_with_copy(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    // manually copy the received message into myBuffer
+    memcpy(myBuffer, msg, size);
+    contribute(regCb2); // Nodegroup reduction to signal completion to the main chare
+  }
+
+  void recv_zc_send_with_copy(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    // manually copy the received message into myBuffer
+    memcpy(myBuffer, msg, size);
+    contribute(zcSendWithCopyCb);
+  }
+
+  void recv_zc_post1(char *&msg, size_t &size, int iter, bool warmUp, int iterations, CkNcpyBufferPost *ncpyPost) {
+    msg = myBuffer;
+    ncpyPost[0].mode = CK_BUFFER_UNREG;
+  }
+
+  void recv_zc_post1(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(zcRecvCb1);
+  }
+
+  void recv_zc_post2(char *&msg, size_t &size, int iter, bool warmUp, int iterations, CkNcpyBufferPost *ncpyPost) {
+    msg = myBuffer;
+    ncpyPost[0].mode = CK_BUFFER_REG;
+  }
+
+  void recv_zc_post2(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(zcRecvCb2);
+  }
+
+  void recv_zc_post3(char *&msg, size_t &size, int iter, bool warmUp, int iterations, CkNcpyBufferPost *ncpyPost) {
+    msg = regBuffer;
+    ncpyPost[0].mode = CK_BUFFER_PREREG;
+  }
+
+  void recv_zc_post3(char *msg, size_t size, int iter, bool warmUp, int iterations) {
+    contribute(zcRecvCb3);
+  }
+};
+
+
+#include "ping_all.def.h"
+
diff --git a/examples/charm++/zerocopy/benchmarks/bcastPingAll/ping_all.ci b/examples/charm++/zerocopy/benchmarks/bcastPingAll/ping_all.ci
new file mode 100644 (file)
index 0000000..46e938f
--- /dev/null
@@ -0,0 +1,58 @@
+mainmodule ping_all
+{
+  readonly CProxy_main mainProxy;
+  readonly int printFormat;
+
+  mainchare main
+  {
+    entry main(CkArgMsg *);
+    entry void start();
+
+    entry [reductiontarget] void recv_done();
+
+    entry void recv_zc_send_free_ptr(CkDataMsg *msg);
+
+    entry [reductiontarget] void recv_zc_send_done1();
+    entry [reductiontarget] void recv_zc_send_done2();
+    entry [reductiontarget] void recv_zc_send_done3();
+    entry [reductiontarget] void recv_with_copy_done();
+    entry [reductiontarget] void recv_zc_send_with_copy_done();
+    entry [reductiontarget] void recv_zc_post_done1();
+    entry [reductiontarget] void recv_zc_post_done2();
+    entry [reductiontarget] void recv_zc_post_done3();
+
+    entry void done();
+  }
+
+  nodegroup LargeDataNodeGroup
+  {
+    entry LargeDataNodeGroup(int maxSize);
+
+    // regular message send api
+    entry [exclusive] void recv(char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message send api for parameters marked "nocopy" (UNREG mode)
+    entry [exclusive] void recv_zc_send1(nocopy char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message send api for parameters marked "nocopy" (REG mode)
+    entry [exclusive] void recv_zc_send2(nocopy char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message send api for parameters marked "nocopy" (PREREG mode)
+    entry [exclusive] void recv_zc_send3(nocopy char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // regular message send api with copy
+    entry [exclusive] void recv_with_copy(char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message send api for parameters marked "nocopy" with copy
+    entry [exclusive] void recv_zc_send_with_copy(nocopy char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message recv api for parameters marked "nocopypost" (UNREG mode)
+    entry [exclusive] void recv_zc_post1(nocopypost char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message recv api for parameters marked "nocopypost" (REG mode)
+    entry [exclusive] void recv_zc_post2(nocopypost char msg[size], size_t size, int iter, bool warmUp, int iterations);
+
+    // charm++ zero copy message recv api for parameters marked "nocopypost" (PREREG mode)
+    entry [exclusive] void recv_zc_post3(nocopypost char msg[size], size_t size, int iter, bool warmUp, int iterations);
+  }
+}