ZC EM Post API: Add examples for each registration mode 80/4980/21
authorNitin Bhat <nbhat4@illinois.edu>
Mon, 25 Feb 2019 22:51:08 +0000 (14:51 -0800)
committerEvan Ramos <evan@hpccharm.com>
Tue, 23 Apr 2019 22:03:28 +0000 (17:03 -0500)
Change-Id: Icae263b84bf8f2ba12a6600e6550af4a63d635aa

31 files changed:
examples/charm++/zerocopy/entry_method_post_api/Makefile
examples/charm++/zerocopy/entry_method_post_api/prereg/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/prereg/nodegroupTest/Makefile [moved from examples/charm++/zerocopy/entry_method_post_api/nodegroupTest/Makefile with 80% similarity]
examples/charm++/zerocopy/entry_method_post_api/prereg/nodegroupTest/nodegroupTest.C [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/prereg/nodegroupTest/nodegroupTest.ci [moved from examples/charm++/zerocopy/entry_method_post_api/nodegroupTest/nodegroupTest.ci with 100% similarity]
examples/charm++/zerocopy/entry_method_post_api/prereg/pingpong/Makefile [moved from examples/charm++/zerocopy/entry_method_post_api/pingpong/Makefile with 69% similarity]
examples/charm++/zerocopy/entry_method_post_api/prereg/pingpong/pingpong.C [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/prereg/pingpong/pingpong.ci [moved from examples/charm++/zerocopy/entry_method_post_api/pingpong/pingpong.ci with 100% similarity]
examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/Makefile [moved from examples/charm++/zerocopy/entry_method_post_api/simpleZeroCopy/Makefile with 86% similarity]
examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/simpleZeroCopy.C [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/simpleZeroCopy.ci [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/nodegroupTest.C [moved from examples/charm++/zerocopy/entry_method_post_api/nodegroupTest/nodegroupTest.C with 100% similarity]
examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/nodegroupTest.ci [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/pingpong.C [moved from examples/charm++/zerocopy/entry_method_post_api/pingpong/pingpong.C with 100% similarity]
examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/pingpong.ci [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/simpleZeroCopy/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/reg/simpleZeroCopy/simpleZeroCopy.C [moved from examples/charm++/zerocopy/entry_method_post_api/simpleZeroCopy/simpleZeroCopy.C with 100% similarity]
examples/charm++/zerocopy/entry_method_post_api/reg/simpleZeroCopy/simpleZeroCopy.ci [moved from examples/charm++/zerocopy/entry_method_post_api/simpleZeroCopy/simpleZeroCopy.ci with 100% similarity]
examples/charm++/zerocopy/entry_method_post_api/unreg/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/nodegroupTest.C [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/nodegroupTest.ci [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/pingpong.C [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/pingpong.ci [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/Makefile [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/simpleZeroCopy.C [new file with mode: 0644]
examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/simpleZeroCopy.ci [new file with mode: 0644]

index 3110d3ae93b237f47f635e9a56788f828d90d1a4..dc0558e334981c69c69b6b2c4658731234415257 100644 (file)
@@ -1,7 +1,7 @@
 DIRS = \
-  pingpong \
-  simpleZeroCopy \
-  nodegroupTest \
+  unreg \
+  prereg \
+  reg \
 
 TESTDIRS = $(DIRS)
 
diff --git a/examples/charm++/zerocopy/entry_method_post_api/prereg/Makefile b/examples/charm++/zerocopy/entry_method_post_api/prereg/Makefile
new file mode 100644 (file)
index 0000000..3110d3a
--- /dev/null
@@ -0,0 +1,23 @@
+DIRS = \
+  pingpong \
+  simpleZeroCopy \
+  nodegroupTest \
+
+TESTDIRS = $(DIRS)
+
+all: $(foreach i,$(DIRS),build-$i)
+
+test: $(foreach i,$(TESTDIRS),test-$i)
+
+clean: $(foreach i,$(DIRS),clean-$i)
+       rm -f TAGS #*#
+       rm -f core *~
+
+$(foreach i,$(DIRS),build-$i):
+       $(MAKE) -C $(subst build-,,$@) all OPTS='$(OPTS)'
+
+$(foreach i,$(DIRS),test-$i):
+       $(MAKE) -C $(subst test-,,$@) test OPTS='$(OPTS)' TESTOPTS='$(TESTOPTS)'
+
+$(foreach i,$(DIRS),clean-$i):
+       $(MAKE) -C $(subst clean-,,$@) clean OPTS='$(OPTS)'
similarity index 80%
rename from examples/charm++/zerocopy/entry_method_post_api/nodegroupTest/Makefile
rename to examples/charm++/zerocopy/entry_method_post_api/prereg/nodegroupTest/Makefile
index 98ee2edc49f6057b21bf74d63b7bdc379f8c9500..93b28dfacc1e522d21b4ed6f115a895ae041f12e 100644 (file)
@@ -1,6 +1,6 @@
--include ../../../../common.mk
--include ../../../../../include/conv-mach-opt.mak
-CHARMC=../../../../../bin/charmc $(OPTS)
+-include ../../../../../common.mk
+-include ../../../../../../include/conv-mach-opt.mak
+CHARMC=../../../../../../bin/charmc $(OPTS)
 
 all: nodegroupTest
 
diff --git a/examples/charm++/zerocopy/entry_method_post_api/prereg/nodegroupTest/nodegroupTest.C b/examples/charm++/zerocopy/entry_method_post_api/prereg/nodegroupTest/nodegroupTest.C
new file mode 100644 (file)
index 0000000..09ab22a
--- /dev/null
@@ -0,0 +1,119 @@
+#include "nodegroupTest.decl.h"
+#include <assert.h>
+
+int numElements;
+CProxy_Main mProxy;
+
+//Main chare
+class Main : public CBase_Main{
+  public:
+    Main(CkArgMsg *m) {
+      if(CkNumNodes() % 2 != 0){
+        ckout<<"Run it on even number of processes"<<endl;
+        CkExit(1);
+      }
+      numElements = CkNumNodes();
+      mProxy = thisProxy;
+      delete m;
+
+      CProxy_zerocopyObject zerocopyObj = CProxy_zerocopyObject::ckNew();
+      zerocopyObj.testZeroCopy();
+    }
+
+    void done(){
+      CkPrintf("All sending completed and result validated\n");
+      CkExit();
+    }
+};
+
+template<class T>
+void compareArray(T *&aArr, T *&bArr, int size, int startIdx=0){
+  for(int i=0; i<size; i++)
+    assert(aArr[i] == bArr[i+startIdx]);
+}
+
+template<class T>
+void copyArray(T *&dest, T *&src, int size){
+  memcpy(dest,src,size*sizeof(T));
+}
+
+template<class T>
+void allocateAndCopyArray(T *&dest, T *&src, int size){
+  dest = new T[size];
+  copyArray(dest, src, size);
+}
+
+template<class T>
+void assignValues(T *&arr, int size){
+  arr = (T *)CkRdmaAlloc(sizeof(T) * size);
+  for(int i=0; i<size; i++)
+     arr[i] = rand() % 100 + 1;
+}
+
+//zerocopy object chare
+class zerocopyObject : public CBase_zerocopyObject{
+  int *iArr1, *iArr1copy;
+  int iSize1;
+  int destIndex;
+
+  CkCallback reductionCb;
+
+  public:
+    zerocopyObject(){
+      destIndex = numElements - 1 - CkMyNode();
+      int idx_maindone = CkIndex_Main::done();
+      reductionCb = CkCallback(idx_maindone, mProxy);
+
+      iSize1 = 210;
+
+      if(CkMyNode() < numElements/2){
+        assignValues(iArr1, iSize1);
+        // copy arrays for comparison
+        allocateAndCopyArray(iArr1copy, iArr1, iSize1);
+      } else {
+        iArr1 = (int *)CkRdmaAlloc(sizeof(int) * iSize1);
+      }
+    }
+
+    zerocopyObject(CkMigrateMessage *m){}
+
+    void testZeroCopy(){
+      if(CkMyNode() < numElements/2){
+        thisProxy[destIndex].zerocopySend(iSize1, CkSendBuffer(iArr1, CK_BUFFER_PREREG));
+      }
+    }
+
+    void zerocopySend(int &n1, int *& ptr1, CkNcpyBufferPost *ncpyPost) {
+      CkAssert(iArr1 != NULL);
+      ptr1 = iArr1;
+
+      ncpyPost[0].mode = CK_BUFFER_PREREG;
+    }
+
+    void zerocopySend(int n1, int *ptr1){
+      if(CkMyNode() < numElements/2){
+        compareArray(iArr1, iArr1copy, n1);
+        if(CkMyNode() == 0)
+          CkPrintf("zerocopySend: completed\n");
+        //contribute to reduction to signal completion
+        contribute(reductionCb);
+      }
+      else{
+        int idx_zerocopySent = CkIndex_zerocopyObject::zerocopySent(NULL);
+        CkCallback cb = CkCallback(idx_zerocopySent, thisProxy[CkMyNode()]);
+        thisProxy[destIndex].zerocopySend(n1, CkSendBuffer(iArr1, cb, CK_BUFFER_PREREG));
+      }
+    }
+
+    void zerocopySent(CkDataMsg *msg) {
+      CkNcpyBuffer *src = (CkNcpyBuffer *)(msg->data);
+      src->deregisterMem();
+      CkRdmaFree((void *)src->ptr);
+      delete msg;
+
+      //contribute to reduction to signal completion
+      contribute(reductionCb);
+    }
+};
+
+#include "nodegroupTest.def.h"
similarity index 69%
rename from examples/charm++/zerocopy/entry_method_post_api/pingpong/Makefile
rename to examples/charm++/zerocopy/entry_method_post_api/prereg/pingpong/Makefile
index 23e468ae4535aa00da6a92b26e02e7e43a11bec9..c648fe660e465ef3f9a5991e1f5cf2be3dae41e4 100644 (file)
@@ -1,5 +1,5 @@
--include ../../../../common.mk
-CHARMC=../../../../../bin/charmc $(OPTS)
+-include ../../../../../common.mk
+CHARMC=../../../../../../bin/charmc $(OPTS)
 
 all:   pgm
 
@@ -17,9 +17,9 @@ pingpong.o: pingpong.C cifiles
 
 test: all
        @echo "Intra-processor Pingpong.."
-       $(call run, ./pgm +p1 )
+       $(call run, +p1 ./pgm 1024 8192 2 1)
        @echo "Inter-processor Pingpong.."
-       $(call run, ./pgm +p2 )
+       $(call run, +p2 ./pgm 1024 8192 2 1)
 
 clean:
        rm -f *.decl.h *.def.h conv-host *.o pgm charmrun cifiles
diff --git a/examples/charm++/zerocopy/entry_method_post_api/prereg/pingpong/pingpong.C b/examples/charm++/zerocopy/entry_method_post_api/prereg/pingpong/pingpong.C
new file mode 100644 (file)
index 0000000..925d320
--- /dev/null
@@ -0,0 +1,161 @@
+#include "pingpong.decl.h"
+
+CProxy_main mainProxy;
+int minSize, maxSize, smallIter, bigIter;
+
+#define P1 0
+#define P2 1%CkNumPes()
+
+class main : public CBase_main
+{
+  CProxy_Ping1 arr1;
+  bool warmUp;
+  int size;
+public:
+  main(CkMigrateMessage *m) {}
+  main(CkArgMsg *m)
+  {
+    if(CkNumPes()>2) {
+      CkAbort("Run this program on 1 or 2 processors only.\n");
+    }
+    if(m->argc == 5) {
+      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]);
+    } else if(m->argc == 1) {
+      // use defaults
+      minSize = 512; // Start with a smaller size to run a warm up phase before starting message size at 1024 bytes
+      maxSize = 1 << 12;
+      smallIter = 1000;
+      bigIter = 100;
+    } else {
+      CkPrintf("Usage: ./pingpong <min size> <max size> <small message iter> <big message iter>\n");
+      CkExit(1);
+    }
+    delete m;
+    size = minSize;
+    mainProxy = thisProxy;
+    warmUp = true;
+    CkPrintf("Size (bytes) \t\tIterations\t\tRegular API (one-way us)\tZero Copy Send API (one-way us)\tZero Copy Send/Recv API (one-way us)\n");
+    arr1 = CProxy_Ping1::ckNew(2);
+    CkStartQD(CkCallback(CkIndex_main::maindone(), mainProxy));
+  }
+
+  void maindone(void){
+    if(size <= maxSize){
+      arr1[0].start(size, warmUp);
+      warmUp = false;
+      size = size << 1;
+    }
+    else{
+      arr1[0].freeBuffer();
+    }
+  }
+};
+
+
+class Ping1 : public CBase_Ping1
+{
+  int size;
+  int niter;
+  int iterations;
+  double start_time, end_time, reg_time, zerocpy_send_time, zerocpy_send_receive_time;
+  char *nocopyMsg;
+
+public:
+  Ping1()
+  {
+    nocopyMsg = (char *)CkRdmaAlloc(sizeof(char) * maxSize);
+    niter = 0;
+  }
+  Ping1(CkMigrateMessage *m) {}
+
+  void start(int size, bool warmUp)
+  {
+    niter = 0;
+    if(size >= 1 << 20)
+      iterations = bigIter;
+    else
+      iterations = smallIter;
+    start_time = CkWallTimer();
+    thisProxy[1].recv(nocopyMsg, size, warmUp);
+  }
+
+  void freeBuffer(){
+    CkRdmaFree(nocopyMsg);
+    if(thisIndex == 0){
+      thisProxy[1].freeBuffer();
+    }
+    else{
+      CkExit();
+    }
+  }
+
+  void recv(char*& msg, int size, bool warmUp)
+  {
+    if(thisIndex==0) {
+      niter++;
+      if(niter==iterations) {
+        end_time = CkWallTimer();
+        reg_time = 1.0e6*(end_time-start_time)/iterations;
+        niter = 0;
+        start_time = CkWallTimer();
+        thisProxy[1].recv_send_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_PREREG), size, warmUp);
+      } else {
+        thisProxy[1].recv(nocopyMsg, size, warmUp);
+      }
+    } else {
+      thisProxy[0].recv(nocopyMsg, size, warmUp);
+    }
+  }
+
+  void recv_send_zerocopy(char* msg, int size, bool warmUp)
+  {
+    if(thisIndex==0) {
+      niter++;
+      if(niter==iterations) {
+        end_time = CkWallTimer();
+        zerocpy_send_time = 1.0e6*(end_time-start_time)/iterations;
+        niter=0;
+        start_time = CkWallTimer();
+        thisProxy[1].recv_send_receive_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_PREREG), size, warmUp);
+      } else {
+        thisProxy[1].recv_send_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_PREREG), size, warmUp);
+      }
+    } else {
+      thisProxy[0].recv_send_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_PREREG), size, warmUp);
+    }
+  }
+
+  void recv_send_receive_zerocopy(char *& msg, int & size, bool & warmUp, CkNcpyBufferPost *ncpyPost) {
+    // post the buffer
+    msg = nocopyMsg;
+
+    ncpyPost[0].mode = CK_BUFFER_PREREG;
+  }
+
+  void recv_send_receive_zerocopy(char *msg, int size, bool warmUp) {
+    if(thisIndex==0) {
+      niter++;
+      if(niter==iterations) {
+        end_time = CkWallTimer();
+        zerocpy_send_receive_time = 1.0e6*(end_time-start_time)/iterations;
+        if(warmUp == false) {
+          if(size < 1 << 24)
+            CkPrintf("%d\t\t\t%d\t\t\t%lf\t\t\t%lf\t\t\t%lf\n", size, iterations, reg_time/2, zerocpy_send_time/2, zerocpy_send_receive_time/2);
+          else //using different print format for larger numbers for aligned output
+            CkPrintf("%d\t\t%d\t\t\t%lf\t\t\t%lf\t\t\t%lf\n", size, iterations, reg_time/2, zerocpy_send_time/2, zerocpy_send_receive_time/2);
+        }
+        niter=0;
+        mainProxy.maindone();
+      } else {
+        thisProxy[1].recv_send_receive_zerocopy(CkSendBuffer(nocopyMsg), size, warmUp);
+      }
+    } else {
+      thisProxy[0].recv_send_receive_zerocopy(CkSendBuffer(nocopyMsg), size, warmUp);
+    }
+  }
+};
+
+#include "pingpong.def.h"
similarity index 86%
rename from examples/charm++/zerocopy/entry_method_post_api/simpleZeroCopy/Makefile
rename to examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/Makefile
index 28f08b07a61d2748da7ca6f131ea8e74a757dd8e..8c3654c2774224480c699dd0878ded020e6e0525 100644 (file)
@@ -1,5 +1,5 @@
--include ../../../../common.mk
-CHARMC=../../../../../bin/charmc $(OPTS)
+-include ../../../../../common.mk
+CHARMC=../../../../../../bin/charmc $(OPTS)
 
 all: simpleZeroCopy
 
diff --git a/examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/simpleZeroCopy.C b/examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/simpleZeroCopy.C
new file mode 100644 (file)
index 0000000..7dde700
--- /dev/null
@@ -0,0 +1,341 @@
+#include "simpleZeroCopy.decl.h"
+#include <assert.h>
+
+//Set DEBUG(x) to x to see the debug messages
+//#define DEBUG(x) x
+#define DEBUG(x)
+#define LBPERIOD_ITER 5
+#define TOTAL_ITER    40
+
+int numElements;
+
+//Main chare
+class Main : public CBase_Main{
+  public:
+    Main(CkArgMsg *m){
+      if(m->argc!=2){
+        ckout<<"Usage: zerocopy <numelements>"<<endl;
+        CkExit(1);
+      }
+      numElements = atoi(m->argv[1]);
+      delete m;
+      if(numElements%2 != 0){
+        ckout<<"Argument <numelements> should be even"<<endl;
+        CkExit(1);
+      }
+
+      CProxy_RRMap rrMap = CProxy_RRMap::ckNew();
+      CkArrayOptions opts(numElements);
+      opts.setMap(rrMap);
+      CProxy_zerocopyObject zerocopyObj = CProxy_zerocopyObject::ckNew(opts);
+      zerocopyObj.testZeroCopy(thisProxy);
+    }
+
+    void done(){
+      CkPrintf("sdagRun: completed\nAll sending completed and result validated\n");
+      CkExit();
+    }
+
+    Main(CkMigrateMessage *m){}
+};
+
+template<class T>
+void compareArray(T *&aArr, T *&bArr, int size, int startIdx=0){
+  for(int i=0; i<size; i++)
+    assert(aArr[i] == bArr[i+startIdx]);
+}
+
+template<class T>
+void copyArray(T *&dest, T *&src, int size){
+  memcpy(dest,src,size*sizeof(T));
+}
+
+
+template<class T>
+void allocateAndCopyArray(T *&dest, T *&src, int size){
+  dest = (T *)CkRdmaAlloc(sizeof(T) * size);
+  copyArray(dest, src, size);
+}
+
+template<class T>
+void assignValues(T *&arr, int size){
+  arr = (T *)CkRdmaAlloc(sizeof(T) * size);
+  for(int i=0; i<size; i++)
+     arr[i] = rand() % 100 + 1;
+}
+
+void assignCharValues(char *&arr, int size){
+  arr = (char *)CkRdmaAlloc(sizeof(char) * size);
+  for(int i=0; i<size; i++)
+     arr[i] = (char)(rand() % 125 + 1);
+}
+
+//zerocopy object chare
+class zerocopyObject : public CBase_zerocopyObject{
+  int *iArr1, *iArr2, *iArr1copy, *iArr2copy;
+  double *dArr1, *dArr2, *dArr1copy, *dArr2copy;
+  char *cArr1, *cArr1copy;
+  int iSize1, iSize2, dSize1, dSize2, cSize1;
+  int destIndex, iter, num, j;
+  int mixedZeroCopySentCounter, sdagZeroCopySentCounter, sdagZeroCopyRecvCounter;
+  bool firstMigrationPending;
+  CkCallback cb, sdagCb;
+  int idx_zerocopySent, idx_sdagZeroCopySent;;
+  CProxy_Main mainProxy;
+
+  public:
+    zerocopyObject_SDAG_CODE
+    zerocopyObject(){
+      usesAtSync = true;
+      destIndex = numElements - 1 - thisIndex;
+      DEBUG(CkPrintf("[%d]  me - %d, my neighbour- %d \n", CkMyNode(), thisIndex, destIndex);)
+      //counter for tracking mixedSend completions to initiate sdagRun
+      mixedZeroCopySentCounter = 0;
+
+      //counter for tracking sdagRecv send completions
+      sdagZeroCopySentCounter = 0;
+
+      //counter for tracking sdagRecv completions
+      sdagZeroCopyRecvCounter = 0;
+      iArr1 = NULL;
+      iArr2 = NULL;
+      dArr1 = NULL;
+      dArr2 = NULL;
+      cArr1 = NULL;
+      iter = 1;
+      num = 4;
+      j = 0;
+      firstMigrationPending = true;
+      idx_zerocopySent = CkIndex_zerocopyObject::zerocopySent(NULL);
+      idx_sdagZeroCopySent = CkIndex_zerocopyObject::sdagZeroCopySent(NULL);
+      cb = CkCallback(idx_zerocopySent, thisProxy[thisIndex]);
+      sdagCb = CkCallback(idx_sdagZeroCopySent, thisProxy[thisIndex]);
+    }
+
+    void pup(PUP::er &p){
+      p|iter;
+      p|destIndex;
+      p|cb;
+      p|num;
+      p|iSize1;
+      p|dSize2;
+      p|mixedZeroCopySentCounter;
+      p|sdagZeroCopySentCounter;
+      p|sdagZeroCopyRecvCounter;
+      p|mainProxy;
+      p|sdagCb;
+
+      // sdagRun only uses iArr1 and dArr2
+      // other others needn't be pupped/unpupped
+      if (p.isUnpacking()){
+        iArr1 = (int *)CkRdmaAlloc(sizeof(int) * iSize1);
+        dArr2 = (double *)CkRdmaAlloc(sizeof(double) * dSize2);
+        iArr1copy = (int *)CkRdmaAlloc(sizeof(int) * iSize1);
+        dArr2copy = (double *)CkRdmaAlloc(sizeof(double) * dSize2);
+        j=0;
+        firstMigrationPending = false;
+      }
+      p(iArr1, iSize1);
+      p(dArr2, dSize2);
+      p(iArr1copy, iSize1);
+      p(dArr2copy, dSize2);
+    }
+
+    ~zerocopyObject() {
+      if(firstMigrationPending) {
+        // delete on first migration on all chares
+        CkRdmaFree(cArr1);
+
+        if(thisIndex < numElements/2) {
+          // delete on first migration on the first set of chares
+          // as it is deleted in the callback on the other set
+          CkRdmaFree(iArr2);
+          CkRdmaFree(dArr1);
+        }
+
+      }
+      // delete everytime after migration as they are pupped to be used for sdagRun
+      CkRdmaFree(dArr2);
+      CkRdmaFree(iArr1);
+    }
+
+    zerocopyObject(CkMigrateMessage *m){}
+
+    void zerocopySent(CkDataMsg *m){
+      // Get access to the array information sent via zerocopy
+      CkNcpyBuffer *src = (CkNcpyBuffer *)(m->data);
+      // de-register the memory
+      src->deregisterMem();
+      CkRdmaFree((void *)(src->ptr));
+
+      delete m;
+
+      if(++mixedZeroCopySentCounter == 2)
+        thisProxy[thisIndex].sdagRun();
+    }
+
+    void sdagZeroCopySent(CkDataMsg *m){
+      // increment on completing the send of an zerocopy parameter in sdagRecv
+      sdagZeroCopySentCounter++;
+
+      // Get access to the array information sent via zerocopy
+      CkNcpyBuffer *src = (CkNcpyBuffer *)(m->data);
+
+      // de-register the memory
+      src->deregisterMem();
+
+      void *ptr = (void *)(src->ptr); // do not free pointer as it is used in the next iteration as well
+
+      delete m;
+
+      // check that all sends and recvs have completed and then advance
+      if(sdagZeroCopySentCounter == 2*num && sdagZeroCopyRecvCounter == num)
+        nextStep();
+    }
+
+    void testZeroCopy(CProxy_Main mProxy){
+      iSize1 = 210;
+      iSize2 = 11;
+      dSize1 = 4700;
+      dSize2 = 79;
+      cSize1 = 32;
+
+      mainProxy = mProxy;
+      if(thisIndex < numElements/2){
+        assignValues(iArr1, iSize1);
+        assignValues(iArr2, iSize2);
+        assignValues(dArr1, dSize1);
+        assignValues(dArr2, dSize2);
+        assignCharValues(cArr1, cSize1);
+
+        // copy arrays for comparison
+        allocateAndCopyArray(iArr1copy, iArr1, iSize1);
+        allocateAndCopyArray(iArr2copy, iArr2, iSize2);
+        allocateAndCopyArray(dArr1copy, dArr1, dSize1);
+        allocateAndCopyArray(dArr2copy, dArr2, dSize2);
+        allocateAndCopyArray(cArr1copy, cArr1, cSize1);
+
+        thisProxy[destIndex].send(iSize1, iArr1, dSize1, dArr1, cSize1, cArr1);
+
+      } else {
+        iArr1 = (int *)CkRdmaAlloc(sizeof(int) * iSize1);
+        iArr2 = (int *)CkRdmaAlloc(sizeof(int) * iSize2);
+        dArr1 = (double *)CkRdmaAlloc(sizeof(double) * dSize1);
+        dArr2 = (double *)CkRdmaAlloc(sizeof(double) * dSize2);
+        cArr1 = (char *)CkRdmaAlloc(sizeof(char) * cSize1);
+      }
+    }
+
+    void send(int n1, int *ptr1, int n2, double *ptr2, int n3, char *ptr3){
+      if(thisIndex < numElements/2){
+        compareArray(ptr1, iArr1, n1);
+        compareArray(ptr2, dArr1, n2);
+        compareArray(ptr3, cArr1, n3);
+        DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": Regular send completed"<<endl;)
+        if(thisIndex == 0)
+          CkPrintf("send: completed\n");
+        thisProxy[destIndex].zerocopySend(iSize1, CkSendBuffer(iArr1, CK_BUFFER_PREREG), dSize1, CkSendBuffer(dArr1, CK_BUFFER_PREREG), cSize1, CkSendBuffer(cArr1, CK_BUFFER_PREREG));
+      }
+      else{
+        thisProxy[destIndex].send(n1, ptr1, n2, ptr2, n3, ptr3);
+      }
+    }
+
+    void zerocopySend(int &n1, int *& ptr1, int &n2, double *& ptr2, int &n3, char *& ptr3, CkNcpyBufferPost *ncpyPost) {
+      DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": ZeroCopy send post"<<endl;)
+      ptr1 = iArr1;
+      ptr2 = dArr1;
+      ptr3 = cArr1;
+
+      ncpyPost[0].mode = CK_BUFFER_PREREG;
+      ncpyPost[1].mode = CK_BUFFER_PREREG;
+      ncpyPost[2].mode = CK_BUFFER_PREREG;
+    }
+
+    void zerocopySend(int n1, int *ptr1, int n2, double *ptr2, int n3, char *ptr3){
+
+      if(thisIndex < numElements/2){
+        compareArray(iArr1, iArr1copy, n1);
+        compareArray(dArr1, dArr1copy, n2);
+        compareArray(cArr1, cArr1copy, n3);
+        DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": ZeroCopy send completed"<<endl;)
+        if(thisIndex == 0)
+          CkPrintf("zerocopySend: completed\n");
+        thisProxy[destIndex].mixedSend(iSize1, iArr1copy, dSize1, CkSendBuffer(dArr1, CK_BUFFER_PREREG), iSize2, CkSendBuffer(iArr2, CK_BUFFER_PREREG), dSize2, dArr2copy);
+      }
+      else{
+        thisProxy[destIndex].zerocopySend(n1, CkSendBuffer(iArr1, CK_BUFFER_PREREG), n2, CkSendBuffer(dArr1, CK_BUFFER_PREREG), n3, CkSendBuffer(cArr1, CK_BUFFER_PREREG));
+      }
+    }
+
+    void mixedSend(int n1, int *ptr1, int n2, double *& ptr2, int n3, int *& ptr3, int n4, double *ptr4, CkNcpyBufferPost *ncpyPost) {
+      ptr2 = dArr1;
+      ptr3 = iArr2;
+
+      ncpyPost[0].mode = CK_BUFFER_PREREG;
+      ncpyPost[1].mode = CK_BUFFER_PREREG;
+    }
+
+    void mixedSend(int n1, int *ptr1, int n2, double *ptr2, int n3, int *ptr3, int n4, double *ptr4){
+      if(thisIndex < numElements/2){
+        compareArray(ptr1, iArr1copy, n1);
+        compareArray(ptr2, dArr1copy, n2); // ptr2 is the same as dArr1
+        compareArray(ptr3, iArr2copy, n3); // ptr3 is the same as iArr2
+        compareArray(ptr4, dArr2copy, n4);
+        DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": Mixed send completed "<<endl;)
+        if(thisIndex == 0)
+          CkPrintf("mixedSend: completed\n");
+        thisProxy[thisIndex].sdagRun();
+      }
+      else{
+        // copy the non-zerocopy arrays
+        copyArray(iArr1, ptr1, n1);
+        copyArray(dArr2, ptr4, n4);
+
+        allocateAndCopyArray(iArr1copy, iArr1, n1);
+        allocateAndCopyArray(dArr2copy, dArr2, n4);
+
+        thisProxy[destIndex].mixedSend(n1, iArr1, n2, CkSendBuffer(dArr1, cb, CK_BUFFER_PREREG), n3, CkSendBuffer(iArr2, cb, CK_BUFFER_PREREG), n4, dArr2);
+      }
+    }
+
+    void nextStep() {
+      // reset the completion counters
+      sdagZeroCopyRecvCounter = 0;
+      sdagZeroCopySentCounter = 0;
+
+      if(thisIndex == 0)
+          CkPrintf("sdagRun: Iteration %d completed\n", iter);
+
+      //increase iteration and continue
+      iter++;
+
+      //load balance
+      if(iter % LBPERIOD_ITER == 0)
+        AtSync();
+      else if(iter<= TOTAL_ITER)
+        thisProxy[thisIndex].sdagRun();
+      else {
+        CkCallback reductionCb(CkReductionTarget(Main, done), mainProxy);
+        contribute(reductionCb);
+      }
+    }
+
+    void sdagRecv(int iter, int &n1, int *& ptr1, int &n2, double *&ptr2, CkNcpyBufferPost *ncpyPost) {
+      ptr1 = iArr1;
+      ptr2 = dArr2;
+      // NOTE: The same arrays are used to receive the data for all the 'num' sdag iterations and
+      // the 'TOTAL_ITER' application iterations. This is entirely for the purpose of demonstration
+      // and results in the same array being overwritten. It is important to note that messages can
+      // be out of order and this could cause correctness issues in real applications if the receiver
+      // doesn't receive the arrays correctly.
+      ncpyPost[0].mode = CK_BUFFER_PREREG;
+      ncpyPost[1].mode = CK_BUFFER_PREREG;
+    }
+
+    void ResumeFromSync() {
+      thisProxy[thisIndex].sdagRun();
+    }
+};
+
+#include "simpleZeroCopy.def.h"
diff --git a/examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/simpleZeroCopy.ci b/examples/charm++/zerocopy/entry_method_post_api/prereg/simpleZeroCopy/simpleZeroCopy.ci
new file mode 100644 (file)
index 0000000..9711e26
--- /dev/null
@@ -0,0 +1,50 @@
+mainmodule simpleZeroCopy {
+
+  readonly int numElements;
+
+  mainchare Main {
+    entry Main(CkArgMsg *m);
+    entry [reductiontarget] void done();
+  };
+
+  array [1D] zerocopyObject{
+    entry zerocopyObject();
+    entry void testZeroCopy(CProxy_Main mProxy);
+    entry void zerocopySent(CkDataMsg *msg);
+    entry void send(int n1, int ptr1[n1], int n2, double ptr2[n2], int n3, char ptr3[n3]);
+    entry void zerocopySend(int n1, nocopypost int ptr1[n1], int n2, nocopypost double ptr2[n2], int n3, nocopypost char ptr3[n3]);
+    entry void mixedSend(int n1, int ptr1[n1], int n2, nocopypost double ptr2[n2], int n3, nocopypost int ptr3[n3], int n4, double ptr4[n4]);
+
+    entry void sdagRun() {
+      serial {
+        // send num arrays to its partner
+        for(int i = 1; i <= num; i++)
+          thisProxy[destIndex].sdagRecv(iter, iSize1, CkSendBuffer(iArr1copy, sdagCb, CK_BUFFER_PREREG), dSize2, CkSendBuffer(dArr2copy, sdagCb, CK_BUFFER_PREREG));
+      }
+
+      // wait for num arrays from partner
+      for (j = 1; j <= num; j++){
+        when sdagRecv[iter] (int iter, int n1, nocopypost int ptr1[n1], int n2, nocopypost double ptr2[n2]){
+
+          serial {
+
+            //CmiPrintf("[%d][%d][%d] sdagRecv actual method %p, %p and received are %p, %p\n", CmiMyPe(), CmiMyNode(), CmiMyRank(), iArr1, dArr2, ptr1, ptr2);
+            // increment counter on receiving a sdagRecv
+            sdagZeroCopyRecvCounter++;
+            compareArray(iArr1, iArr1copy, n1);
+            compareArray(dArr2, dArr2copy, n2);
+
+            // check that all sends and recvs have completed and then advance
+            //CmiPrintf("[%d][%d][%d] SdagRun recvcounter=%d, sentcounter=%d, num=%d\n", CmiMyPe(), CmiMyNode(), CmiMyRank(), sdagZeroCopyRecvCounter, sdagZeroCopySentCounter, num);
+            if(sdagZeroCopySentCounter == 2*num && sdagZeroCopyRecvCounter == num)
+              nextStep();
+          }
+        }
+      }
+    }
+
+    entry void sdagZeroCopySent(CkDataMsg *msg);
+    entry void sdagRecv(int iter, int n1, nocopypost int ptr1[n1], int n2, nocopypost double ptr2[n2]);
+  };
+
+}
diff --git a/examples/charm++/zerocopy/entry_method_post_api/reg/Makefile b/examples/charm++/zerocopy/entry_method_post_api/reg/Makefile
new file mode 100644 (file)
index 0000000..3110d3a
--- /dev/null
@@ -0,0 +1,23 @@
+DIRS = \
+  pingpong \
+  simpleZeroCopy \
+  nodegroupTest \
+
+TESTDIRS = $(DIRS)
+
+all: $(foreach i,$(DIRS),build-$i)
+
+test: $(foreach i,$(TESTDIRS),test-$i)
+
+clean: $(foreach i,$(DIRS),clean-$i)
+       rm -f TAGS #*#
+       rm -f core *~
+
+$(foreach i,$(DIRS),build-$i):
+       $(MAKE) -C $(subst build-,,$@) all OPTS='$(OPTS)'
+
+$(foreach i,$(DIRS),test-$i):
+       $(MAKE) -C $(subst test-,,$@) test OPTS='$(OPTS)' TESTOPTS='$(TESTOPTS)'
+
+$(foreach i,$(DIRS),clean-$i):
+       $(MAKE) -C $(subst clean-,,$@) clean OPTS='$(OPTS)'
diff --git a/examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/Makefile b/examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/Makefile
new file mode 100644 (file)
index 0000000..93b28df
--- /dev/null
@@ -0,0 +1,25 @@
+-include ../../../../../common.mk
+-include ../../../../../../include/conv-mach-opt.mak
+CHARMC=../../../../../../bin/charmc $(OPTS)
+
+all: nodegroupTest
+
+nodegroupTest:  nodegroupTest.o
+       $(CHARMC) nodegroupTest.o -o nodegroupTest -language charm++ -module CommonLBs
+
+cifiles: nodegroupTest.ci
+       $(CHARMC) -c nodegroupTest.ci
+       touch cifiles
+
+nodegroupTest.o : nodegroupTest.C cifiles
+       $(CHARMC) -c nodegroupTest.C
+
+test: all
+ifeq ($(CMK_MULTICORE),1)
+       echo "Skipping nodegroupTest test on MULTICORE builds as it has to be run on even number of logical nodes"
+else
+       $(call run, +p4 ./nodegroupTest)
+endif
+
+clean:
+       rm -f *.def.h *.decl.h *.o *~ *.exe cifiles charmrun nodegroupTest
diff --git a/examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/nodegroupTest.ci b/examples/charm++/zerocopy/entry_method_post_api/reg/nodegroupTest/nodegroupTest.ci
new file mode 100644 (file)
index 0000000..33e9eda
--- /dev/null
@@ -0,0 +1,17 @@
+mainmodule nodegroupTest {
+
+  readonly int numElements;
+  readonly CProxy_Main mProxy;
+
+  mainchare Main {
+    entry Main(CkArgMsg *m);
+    entry [reductiontarget] void done();
+  };
+
+  nodegroup zerocopyObject{
+    entry zerocopyObject();
+    entry void testZeroCopy();
+    entry void zerocopySend(int n1, nocopypost int ptr1[n1]);
+    entry void zerocopySent(CkDataMsg *msg);
+  };
+}
diff --git a/examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/Makefile b/examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/Makefile
new file mode 100644 (file)
index 0000000..c648fe6
--- /dev/null
@@ -0,0 +1,25 @@
+-include ../../../../../common.mk
+CHARMC=../../../../../../bin/charmc $(OPTS)
+
+all:   pgm
+
+OBJS = pingpong.o
+
+pgm: $(OBJS)
+       $(CHARMC) -language charm++ -o pgm $(OBJS)
+
+cifiles: pingpong.ci
+       $(CHARMC)  pingpong.ci
+       touch cifiles
+
+pingpong.o: pingpong.C cifiles
+       $(CHARMC) -c pingpong.C
+
+test: all
+       @echo "Intra-processor Pingpong.."
+       $(call run, +p1 ./pgm 1024 8192 2 1)
+       @echo "Inter-processor Pingpong.."
+       $(call run, +p2 ./pgm 1024 8192 2 1)
+
+clean:
+       rm -f *.decl.h *.def.h conv-host *.o pgm charmrun cifiles
diff --git a/examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/pingpong.ci b/examples/charm++/zerocopy/entry_method_post_api/reg/pingpong/pingpong.ci
new file mode 100644 (file)
index 0000000..18205d9
--- /dev/null
@@ -0,0 +1,22 @@
+mainmodule pingpong {
+
+  readonly CProxy_main mainProxy;
+  readonly int minSize;
+  readonly int maxSize;
+  readonly int smallIter;
+  readonly int bigIter;
+
+  mainchare main {
+    entry main(CkArgMsg *m);
+    entry void maindone(void);
+  };
+
+  array [1D] Ping1 {
+    entry Ping1();
+    entry void start(int size, bool warmUp);
+    entry void freeBuffer();
+    entry void recv(char msg[size], int size, bool warmUp);
+    entry void recv_send_zerocopy(nocopy char msg[size], int size, bool warmUp);
+    entry void recv_send_receive_zerocopy(nocopypost char msg[size], int size, bool warmUp);
+  };
+};
diff --git a/examples/charm++/zerocopy/entry_method_post_api/reg/simpleZeroCopy/Makefile b/examples/charm++/zerocopy/entry_method_post_api/reg/simpleZeroCopy/Makefile
new file mode 100644 (file)
index 0000000..8c3654c
--- /dev/null
@@ -0,0 +1,21 @@
+-include ../../../../../common.mk
+CHARMC=../../../../../../bin/charmc $(OPTS)
+
+all: simpleZeroCopy
+
+simpleZeroCopy:  simpleZeroCopy.o
+       $(CHARMC) simpleZeroCopy.o -o simpleZeroCopy -language charm++ -module CommonLBs
+
+cifiles: simpleZeroCopy.ci
+       $(CHARMC) -c simpleZeroCopy.ci
+       touch cifiles
+
+simpleZeroCopy.o : simpleZeroCopy.C cifiles
+       $(CHARMC) -c simpleZeroCopy.C
+
+test: all
+       $(call run, +p4 ./simpleZeroCopy 32 +balancer RotateLB)
+       $(call run, +p4 ./simpleZeroCopy 32 +balancer GreedyLB)
+
+clean:
+       rm -f *.def.h *.decl.h *.o *~ *.exe cifiles charmrun simpleZeroCopy
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/Makefile b/examples/charm++/zerocopy/entry_method_post_api/unreg/Makefile
new file mode 100644 (file)
index 0000000..3110d3a
--- /dev/null
@@ -0,0 +1,23 @@
+DIRS = \
+  pingpong \
+  simpleZeroCopy \
+  nodegroupTest \
+
+TESTDIRS = $(DIRS)
+
+all: $(foreach i,$(DIRS),build-$i)
+
+test: $(foreach i,$(TESTDIRS),test-$i)
+
+clean: $(foreach i,$(DIRS),clean-$i)
+       rm -f TAGS #*#
+       rm -f core *~
+
+$(foreach i,$(DIRS),build-$i):
+       $(MAKE) -C $(subst build-,,$@) all OPTS='$(OPTS)'
+
+$(foreach i,$(DIRS),test-$i):
+       $(MAKE) -C $(subst test-,,$@) test OPTS='$(OPTS)' TESTOPTS='$(TESTOPTS)'
+
+$(foreach i,$(DIRS),clean-$i):
+       $(MAKE) -C $(subst clean-,,$@) clean OPTS='$(OPTS)'
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/Makefile b/examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/Makefile
new file mode 100644 (file)
index 0000000..93b28df
--- /dev/null
@@ -0,0 +1,25 @@
+-include ../../../../../common.mk
+-include ../../../../../../include/conv-mach-opt.mak
+CHARMC=../../../../../../bin/charmc $(OPTS)
+
+all: nodegroupTest
+
+nodegroupTest:  nodegroupTest.o
+       $(CHARMC) nodegroupTest.o -o nodegroupTest -language charm++ -module CommonLBs
+
+cifiles: nodegroupTest.ci
+       $(CHARMC) -c nodegroupTest.ci
+       touch cifiles
+
+nodegroupTest.o : nodegroupTest.C cifiles
+       $(CHARMC) -c nodegroupTest.C
+
+test: all
+ifeq ($(CMK_MULTICORE),1)
+       echo "Skipping nodegroupTest test on MULTICORE builds as it has to be run on even number of logical nodes"
+else
+       $(call run, +p4 ./nodegroupTest)
+endif
+
+clean:
+       rm -f *.def.h *.decl.h *.o *~ *.exe cifiles charmrun nodegroupTest
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/nodegroupTest.C b/examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/nodegroupTest.C
new file mode 100644 (file)
index 0000000..5f06029
--- /dev/null
@@ -0,0 +1,120 @@
+#include "nodegroupTest.decl.h"
+#include <assert.h>
+
+int numElements;
+CProxy_Main mProxy;
+
+//Main chare
+class Main : public CBase_Main{
+  public:
+    Main(CkArgMsg *m) {
+      if(CkNumNodes() % 2 != 0){
+        ckout<<"Run it on even number of processes"<<endl;
+        CkExit(1);
+      }
+      delete m;
+
+      numElements = CkNumNodes();
+      mProxy = thisProxy;
+
+      CProxy_zerocopyObject zerocopyObj = CProxy_zerocopyObject::ckNew();
+      zerocopyObj.testZeroCopy();
+    }
+
+    void done(){
+      CkPrintf("All sending completed and result validated\n");
+      CkExit();
+    }
+};
+
+template<class T>
+void compareArray(T *&aArr, T *&bArr, int size, int startIdx=0){
+  for(int i=0; i<size; i++)
+    assert(aArr[i] == bArr[i+startIdx]);
+}
+
+template<class T>
+void copyArray(T *&dest, T *&src, int size){
+  memcpy(dest,src,size*sizeof(T));
+}
+
+template<class T>
+void allocateAndCopyArray(T *&dest, T *&src, int size){
+  dest = new T[size];
+  copyArray(dest, src, size);
+}
+
+template<class T>
+void assignValues(T *&arr, int size){
+  arr = new T[size];
+  for(int i=0; i<size; i++)
+     arr[i] = rand() % 100 + 1;
+}
+
+//zerocopy object chare
+class zerocopyObject : public CBase_zerocopyObject{
+  int *iArr1, *iArr1copy;
+  int iSize1;
+  int destIndex;
+
+  CkCallback reductionCb;
+
+  public:
+    zerocopyObject(){
+      destIndex = numElements - 1 - CkMyNode();
+      int idx_maindone = CkIndex_Main::done();
+      reductionCb = CkCallback(idx_maindone, mProxy);
+
+      iSize1 = 210;
+
+      if(CkMyNode() < numElements/2){
+        assignValues(iArr1, iSize1);
+        // copy arrays for comparison
+        allocateAndCopyArray(iArr1copy, iArr1, iSize1);
+      } else {
+        iArr1 = new int[iSize1];
+      }
+    }
+
+    zerocopyObject(CkMigrateMessage *m){}
+
+    void testZeroCopy(){
+      if(CkMyNode() < numElements/2){
+        thisProxy[destIndex].zerocopySend(iSize1, CkSendBuffer(iArr1, CK_BUFFER_UNREG));
+      }
+    }
+
+    void zerocopySend(int &n1, int *& ptr1, CkNcpyBufferPost *ncpyPost) {
+      CkAssert(iArr1 != NULL);
+      ptr1 = iArr1;
+
+      ncpyPost[0].mode = CK_BUFFER_UNREG;
+    }
+
+    void zerocopySend(int n1, int *ptr1){
+      if(CkMyNode() < numElements/2){
+        compareArray(iArr1, iArr1copy, n1);
+        if(CkMyNode() == 0)
+          CkPrintf("zerocopySend: completed\n");
+        //contribute to reduction to signal completion
+        contribute(reductionCb);
+      }
+      else{
+        int idx_zerocopySent = CkIndex_zerocopyObject::zerocopySent(NULL);
+        CkCallback cb = CkCallback(idx_zerocopySent, thisProxy[CkMyNode()]);
+        thisProxy[destIndex].zerocopySend(n1, CkSendBuffer(iArr1, cb, CK_BUFFER_UNREG));
+      }
+    }
+
+    void zerocopySent(CkDataMsg *msg) {
+      CkNcpyBuffer *src = (CkNcpyBuffer *)(msg->data);
+      src->deregisterMem();
+      delete [] (int *)(src->ptr);
+      delete msg;
+
+      //contribute to reduction to signal completion
+      contribute(reductionCb);
+    }
+};
+
+#include "nodegroupTest.def.h"
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/nodegroupTest.ci b/examples/charm++/zerocopy/entry_method_post_api/unreg/nodegroupTest/nodegroupTest.ci
new file mode 100644 (file)
index 0000000..33e9eda
--- /dev/null
@@ -0,0 +1,17 @@
+mainmodule nodegroupTest {
+
+  readonly int numElements;
+  readonly CProxy_Main mProxy;
+
+  mainchare Main {
+    entry Main(CkArgMsg *m);
+    entry [reductiontarget] void done();
+  };
+
+  nodegroup zerocopyObject{
+    entry zerocopyObject();
+    entry void testZeroCopy();
+    entry void zerocopySend(int n1, nocopypost int ptr1[n1]);
+    entry void zerocopySent(CkDataMsg *msg);
+  };
+}
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/Makefile b/examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/Makefile
new file mode 100644 (file)
index 0000000..c648fe6
--- /dev/null
@@ -0,0 +1,25 @@
+-include ../../../../../common.mk
+CHARMC=../../../../../../bin/charmc $(OPTS)
+
+all:   pgm
+
+OBJS = pingpong.o
+
+pgm: $(OBJS)
+       $(CHARMC) -language charm++ -o pgm $(OBJS)
+
+cifiles: pingpong.ci
+       $(CHARMC)  pingpong.ci
+       touch cifiles
+
+pingpong.o: pingpong.C cifiles
+       $(CHARMC) -c pingpong.C
+
+test: all
+       @echo "Intra-processor Pingpong.."
+       $(call run, +p1 ./pgm 1024 8192 2 1)
+       @echo "Inter-processor Pingpong.."
+       $(call run, +p2 ./pgm 1024 8192 2 1)
+
+clean:
+       rm -f *.decl.h *.def.h conv-host *.o pgm charmrun cifiles
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/pingpong.C b/examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/pingpong.C
new file mode 100644 (file)
index 0000000..43444ae
--- /dev/null
@@ -0,0 +1,161 @@
+#include "pingpong.decl.h"
+
+CProxy_main mainProxy;
+int minSize, maxSize, smallIter, bigIter;
+
+#define P1 0
+#define P2 1%CkNumPes()
+
+class main : public CBase_main
+{
+  CProxy_Ping1 arr1;
+  bool warmUp;
+  int size;
+public:
+  main(CkMigrateMessage *m) {}
+  main(CkArgMsg *m)
+  {
+    if(CkNumPes()>2) {
+      CkAbort("Run this program on 1 or 2 processors only.\n");
+    }
+    if(m->argc == 5) {
+      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]);
+    } else if(m->argc == 1) {
+      // use defaults
+      minSize = 512; // Start with a smaller size to run a warm up phase before starting message size at 1024 bytes
+      maxSize = 1 << 12;
+      smallIter = 1000;
+      bigIter = 100;
+    } else {
+      CkPrintf("Usage: ./pingpong <min size> <max size> <small message iter> <big message iter>\n");
+      CkExit(1);
+    }
+    delete m;
+    size = minSize;
+    mainProxy = thisProxy;
+    warmUp = true;
+    CkPrintf("Size (bytes) \t\tIterations\t\tRegular API (one-way us)\tZero Copy Send API (one-way us)\tZero Copy Send/Recv API (one-way us)\n");
+    arr1 = CProxy_Ping1::ckNew(2);
+    CkStartQD(CkCallback(CkIndex_main::maindone(), mainProxy));
+  }
+
+  void maindone(void){
+    if(size <= maxSize){
+      arr1[0].start(size, warmUp);
+      warmUp = false;
+      size = size << 1;
+    }
+    else{
+      arr1[0].freeBuffer();
+    }
+  }
+};
+
+
+class Ping1 : public CBase_Ping1
+{
+  int size;
+  int niter;
+  int iterations;
+  double start_time, end_time, reg_time, zerocpy_send_time, zerocpy_send_receive_time;
+  char *nocopyMsg;
+
+public:
+  Ping1()
+  {
+    nocopyMsg = new char[maxSize];
+    niter = 0;
+  }
+  Ping1(CkMigrateMessage *m) {}
+
+  void start(int size, bool warmUp)
+  {
+    niter = 0;
+    if(size >= 1 << 20)
+      iterations = bigIter;
+    else
+      iterations = smallIter;
+    start_time = CkWallTimer();
+    thisProxy[1].recv(nocopyMsg, size, warmUp);
+  }
+
+  void freeBuffer(){
+    delete [] nocopyMsg;
+    if(thisIndex == 0){
+      thisProxy[1].freeBuffer();
+    }
+    else{
+      CkExit();
+    }
+  }
+
+  void recv(char*& msg, int size, bool warmUp)
+  {
+    if(thisIndex==0) {
+      niter++;
+      if(niter==iterations) {
+        end_time = CkWallTimer();
+        reg_time = 1.0e6*(end_time-start_time)/iterations;
+        niter = 0;
+        start_time = CkWallTimer();
+        thisProxy[1].recv_send_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_UNREG), size, warmUp);
+      } else {
+        thisProxy[1].recv(nocopyMsg, size, warmUp);
+      }
+    } else {
+      thisProxy[0].recv(nocopyMsg, size, warmUp);
+    }
+  }
+
+  void recv_send_zerocopy(char* msg, int size, bool warmUp)
+  {
+    if(thisIndex==0) {
+      niter++;
+      if(niter==iterations) {
+        end_time = CkWallTimer();
+        zerocpy_send_time = 1.0e6*(end_time-start_time)/iterations;
+        niter=0;
+        start_time = CkWallTimer();
+        thisProxy[1].recv_send_receive_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_UNREG), size, warmUp);
+      } else {
+        thisProxy[1].recv_send_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_UNREG), size, warmUp);
+      }
+    } else {
+      thisProxy[0].recv_send_zerocopy(CkSendBuffer(nocopyMsg, CK_BUFFER_UNREG), size, warmUp);
+    }
+  }
+
+  void recv_send_receive_zerocopy(char *& msg, int & size, bool & warmUp, CkNcpyBufferPost *ncpyPost) {
+    // post the buffer
+    msg = nocopyMsg;
+
+    ncpyPost[0].mode = CK_BUFFER_UNREG;
+  }
+
+  void recv_send_receive_zerocopy(char *msg, int size, bool warmUp) {
+    if(thisIndex==0) {
+      niter++;
+      if(niter==iterations) {
+        end_time = CkWallTimer();
+        zerocpy_send_receive_time = 1.0e6*(end_time-start_time)/iterations;
+        if(warmUp == false) {
+          if(size < 1 << 24)
+            CkPrintf("%d\t\t\t%d\t\t\t%lf\t\t\t%lf\t\t\t%lf\n", size, iterations, reg_time/2, zerocpy_send_time/2, zerocpy_send_receive_time/2);
+          else //using different print format for larger numbers for aligned output
+            CkPrintf("%d\t\t%d\t\t\t%lf\t\t\t%lf\t\t\t%lf\n", size, iterations, reg_time/2, zerocpy_send_time/2, zerocpy_send_receive_time/2);
+        }
+        niter=0;
+        mainProxy.maindone();
+      } else {
+        thisProxy[1].recv_send_receive_zerocopy(CkSendBuffer(nocopyMsg), size, warmUp);
+      }
+    } else {
+      thisProxy[0].recv_send_receive_zerocopy(CkSendBuffer(nocopyMsg), size, warmUp);
+    }
+  }
+};
+
+#include "pingpong.def.h"
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/pingpong.ci b/examples/charm++/zerocopy/entry_method_post_api/unreg/pingpong/pingpong.ci
new file mode 100644 (file)
index 0000000..18205d9
--- /dev/null
@@ -0,0 +1,22 @@
+mainmodule pingpong {
+
+  readonly CProxy_main mainProxy;
+  readonly int minSize;
+  readonly int maxSize;
+  readonly int smallIter;
+  readonly int bigIter;
+
+  mainchare main {
+    entry main(CkArgMsg *m);
+    entry void maindone(void);
+  };
+
+  array [1D] Ping1 {
+    entry Ping1();
+    entry void start(int size, bool warmUp);
+    entry void freeBuffer();
+    entry void recv(char msg[size], int size, bool warmUp);
+    entry void recv_send_zerocopy(nocopy char msg[size], int size, bool warmUp);
+    entry void recv_send_receive_zerocopy(nocopypost char msg[size], int size, bool warmUp);
+  };
+};
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/Makefile b/examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/Makefile
new file mode 100644 (file)
index 0000000..8c3654c
--- /dev/null
@@ -0,0 +1,21 @@
+-include ../../../../../common.mk
+CHARMC=../../../../../../bin/charmc $(OPTS)
+
+all: simpleZeroCopy
+
+simpleZeroCopy:  simpleZeroCopy.o
+       $(CHARMC) simpleZeroCopy.o -o simpleZeroCopy -language charm++ -module CommonLBs
+
+cifiles: simpleZeroCopy.ci
+       $(CHARMC) -c simpleZeroCopy.ci
+       touch cifiles
+
+simpleZeroCopy.o : simpleZeroCopy.C cifiles
+       $(CHARMC) -c simpleZeroCopy.C
+
+test: all
+       $(call run, +p4 ./simpleZeroCopy 32 +balancer RotateLB)
+       $(call run, +p4 ./simpleZeroCopy 32 +balancer GreedyLB)
+
+clean:
+       rm -f *.def.h *.decl.h *.o *~ *.exe cifiles charmrun simpleZeroCopy
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/simpleZeroCopy.C b/examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/simpleZeroCopy.C
new file mode 100644 (file)
index 0000000..d7f43c7
--- /dev/null
@@ -0,0 +1,344 @@
+#include "simpleZeroCopy.decl.h"
+#include <assert.h>
+
+//Set DEBUG(x) to x to see the debug messages
+//#define DEBUG(x) x
+#define DEBUG(x)
+#define LBPERIOD_ITER 5
+#define TOTAL_ITER    40
+
+int numElements;
+
+//Main chare
+class Main : public CBase_Main{
+  public:
+    Main(CkArgMsg *m){
+      if(m->argc!=2){
+        ckout<<"Usage: zerocopy <numelements>"<<endl;
+        CkExit(1);
+      }
+      numElements = atoi(m->argv[1]);
+      delete m;
+      if(numElements%2 != 0){
+        ckout<<"Argument <numelements> should be even"<<endl;
+        CkExit(1);
+      }
+
+      CProxy_RRMap rrMap = CProxy_RRMap::ckNew();
+      CkArrayOptions opts(numElements);
+      opts.setMap(rrMap);
+      CProxy_zerocopyObject zerocopyObj = CProxy_zerocopyObject::ckNew(opts);
+      zerocopyObj.testZeroCopy(thisProxy);
+    }
+
+    void done(){
+      CkPrintf("sdagRun: completed\nAll sending completed and result validated\n");
+      CkExit();
+    }
+
+    Main(CkMigrateMessage *m){}
+};
+
+template<class T>
+void compareArray(T *&aArr, T *&bArr, int size, int startIdx=0){
+  for(int i=0; i<size; i++)
+    assert(aArr[i] == bArr[i+startIdx]);
+}
+
+template<class T>
+void copyArray(T *&dest, T *&src, int size){
+  memcpy(dest,src,size*sizeof(T));
+}
+
+
+template<class T>
+void allocateAndCopyArray(T *&dest, T *&src, int size){
+  dest = new T[size];
+  copyArray(dest, src, size);
+}
+
+template<class T>
+void assignValues(T *&arr, int size){
+  arr = new T[size];
+  for(int i=0; i<size; i++)
+     arr[i] = rand() % 100 + 1;
+}
+
+void assignCharValues(char *&arr, int size){
+  arr = new char[size];
+  for(int i=0; i<size; i++)
+     arr[i] = (char)(rand() % 125 + 1);
+}
+
+//zerocopy object chare
+class zerocopyObject : public CBase_zerocopyObject{
+  int *iArr1, *iArr2, *iArr1copy, *iArr2copy;
+  double *dArr1, *dArr2, *dArr1copy, *dArr2copy;
+  char *cArr1, *cArr1copy;
+  int iSize1, iSize2, dSize1, dSize2, cSize1, iOffset1, cOffset1;
+  int destIndex, iter, num, j;
+  int mixedZeroCopySentCounter, sdagZeroCopySentCounter, sdagZeroCopyRecvCounter;
+  bool firstMigrationPending;
+  CkCallback cb, sdagCb;
+  int idx_zerocopySent, idx_sdagZeroCopySent;;
+  CProxy_Main mainProxy;
+
+  public:
+    zerocopyObject_SDAG_CODE
+    zerocopyObject(){
+      usesAtSync = true;
+      destIndex = numElements - 1 - thisIndex;
+      DEBUG(CkPrintf("[%d]  me - %d, my neighbour- %d \n", CkMyNode(), thisIndex, destIndex);)
+      //counter for tracking mixedSend completions to initiate sdagRun
+      mixedZeroCopySentCounter = 0;
+
+      //counter for tracking sdagRecv send completions
+      sdagZeroCopySentCounter = 0;
+
+      //counter for tracking sdagRecv completions
+      sdagZeroCopyRecvCounter = 0;
+      iArr1 = NULL;
+      iArr2 = NULL;
+      dArr1 = NULL;
+      dArr2 = NULL;
+      cArr1 = NULL;
+      iter = 1;
+      num = 4;
+      j = 0;
+      firstMigrationPending = true;
+      idx_zerocopySent = CkIndex_zerocopyObject::zerocopySent(NULL);
+      idx_sdagZeroCopySent = CkIndex_zerocopyObject::sdagZeroCopySent(NULL);
+      cb = CkCallback(idx_zerocopySent, thisProxy[thisIndex]);
+      sdagCb = CkCallback(idx_sdagZeroCopySent, thisProxy[thisIndex]);
+    }
+
+    void pup(PUP::er &p){
+      p|iter;
+      p|destIndex;
+      p|cb;
+      p|num;
+      p|iSize1;
+      p|dSize2;
+      p|mixedZeroCopySentCounter;
+      p|sdagZeroCopySentCounter;
+      p|sdagZeroCopyRecvCounter;
+      p|mainProxy;
+      p|sdagCb;
+
+      // sdagRun only uses iArr1 and dArr2
+      // other others needn't be pupped/unpupped
+      if (p.isUnpacking()){
+        iArr1 = new int[iSize1];
+        dArr2 = new double[dSize2];
+        iArr1copy = new int[iSize1];
+        dArr2copy = new double[dSize2];
+        j=0;
+        firstMigrationPending = false;
+      }
+      p(iArr1, iSize1);
+      p(dArr2, dSize2);
+      p(iArr1copy, iSize1);
+      p(dArr2copy, dSize2);
+    }
+
+    ~zerocopyObject() {
+      if(firstMigrationPending) {
+        // delete on first migration on all chares
+        delete [] cArr1;
+
+        if(thisIndex < numElements/2) {
+          // delete on first migration on the first set of chares
+          // as it is deleted in the callback on the other set
+          delete [] iArr2;
+          delete [] dArr1;
+        }
+
+      }
+      // delete everytime after migration as they are pupped to be used for sdagRun
+      delete [] dArr2;
+      delete [] iArr1;
+    }
+
+    zerocopyObject(CkMigrateMessage *m){}
+
+    void zerocopySent(CkDataMsg *m){
+      // Get access to the array information sent via zerocopy
+      CkNcpyBuffer *src = (CkNcpyBuffer *)(m->data);
+      // de-register the memory
+      src->deregisterMem();
+      free((void *)(src->ptr));
+
+      delete m;
+
+      if(++mixedZeroCopySentCounter == 2)
+        thisProxy[thisIndex].sdagRun();
+    }
+
+    void sdagZeroCopySent(CkDataMsg *m){
+      // increment on completing the send of an zerocopy parameter in sdagRecv
+      sdagZeroCopySentCounter++;
+
+      // Get access to the array information sent via zerocopy
+      CkNcpyBuffer *src = (CkNcpyBuffer *)(m->data);
+
+      // de-register the memory
+      src->deregisterMem();
+
+      void *ptr = (void *)(src->ptr); // do not free pointer as it is used in the next iteration as well
+
+      delete m;
+
+      // check that all sends and recvs have completed and then advance
+      if(sdagZeroCopySentCounter == 2*num && sdagZeroCopyRecvCounter == num)
+        nextStep();
+    }
+
+    void testZeroCopy(CProxy_Main mProxy){
+      iSize1 = 210;
+      iSize2 = 11;
+      dSize1 = 4700;
+      dSize2 = 79;
+      cSize1 = 32;
+
+      iOffset1 = 3;
+      cOffset1 = 2;
+
+      mainProxy = mProxy;
+      if(thisIndex < numElements/2){
+        assignValues(iArr1, iSize1);
+        assignValues(iArr2, iSize2);
+        assignValues(dArr1, dSize1);
+        assignValues(dArr2, dSize2);
+        assignCharValues(cArr1, cSize1);
+
+        // copy arrays for comparison
+        allocateAndCopyArray(iArr1copy, iArr1, iSize1);
+        allocateAndCopyArray(iArr2copy, iArr2, iSize2);
+        allocateAndCopyArray(dArr1copy, dArr1, dSize1);
+        allocateAndCopyArray(dArr2copy, dArr2, dSize2);
+        allocateAndCopyArray(cArr1copy, cArr1, cSize1);
+
+        thisProxy[destIndex].send(iSize1, iArr1, dSize1, dArr1, cSize1, cArr1);
+
+      } else {
+        iArr1 = new int[iSize1];
+        iArr2 = new int[iSize2];
+        dArr1 = new double[dSize1];
+        dArr2 = new double[dSize2];
+        cArr1 = new char[cSize1];
+      }
+    }
+
+    void send(int n1, int *ptr1, int n2, double *ptr2, int n3, char *ptr3){
+      if(thisIndex < numElements/2){
+        compareArray(ptr1, iArr1, n1);
+        compareArray(ptr2, dArr1, n2);
+        compareArray(ptr3, cArr1, n3);
+        DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": Regular send completed"<<endl;)
+        if(thisIndex == 0)
+          CkPrintf("send: completed\n");
+        thisProxy[destIndex].zerocopySend(iSize1-iOffset1, CkSendBuffer(iArr1+iOffset1, CK_BUFFER_UNREG), dSize1, CkSendBuffer(dArr1, CK_BUFFER_UNREG), cSize1-cOffset1, CkSendBuffer(cArr1 + cOffset1, CK_BUFFER_UNREG));
+      }
+      else{
+        thisProxy[destIndex].send(n1, ptr1, n2, ptr2, n3, ptr3);
+      }
+    }
+
+    void zerocopySend(int &n1, int *& ptr1, int &n2, double *& ptr2, int &n3, char *& ptr3, CkNcpyBufferPost *ncpyPost) {
+      DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": ZeroCopy send post"<<endl;)
+      ptr1 = iArr1;
+      ptr2 = dArr1;
+      ptr3 = cArr1;
+
+      ncpyPost[0].mode = CK_BUFFER_UNREG;
+      ncpyPost[1].mode = CK_BUFFER_UNREG;
+      ncpyPost[2].mode = CK_BUFFER_UNREG;
+    }
+
+    void zerocopySend(int n1, int *ptr1, int n2, double *ptr2, int n3, char *ptr3){
+
+      if(thisIndex < numElements/2){
+        compareArray(iArr1, iArr1copy, n1, iOffset1);
+        compareArray(dArr1, dArr1copy, n2);
+        compareArray(cArr1, cArr1copy, n3, cOffset1);
+        DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": ZeroCopy send completed"<<endl;)
+        if(thisIndex == 0)
+          CkPrintf("zerocopySend: completed\n");
+        thisProxy[destIndex].mixedSend(iSize1, iArr1copy, dSize1, CkSendBuffer(dArr1, CK_BUFFER_UNREG), iSize2, CkSendBuffer(iArr2, CK_BUFFER_UNREG), dSize2, dArr2copy);
+      }
+      else{
+        thisProxy[destIndex].zerocopySend(n1, CkSendBuffer(iArr1, CK_BUFFER_UNREG), n2, CkSendBuffer(dArr1, CK_BUFFER_UNREG), n3, CkSendBuffer(cArr1, CK_BUFFER_UNREG));
+      }
+    }
+
+    void mixedSend(int n1, int *ptr1, int n2, double *& ptr2, int n3, int *& ptr3, int n4, double *ptr4, CkNcpyBufferPost *ncpyPost) {
+      ptr2 = dArr1;
+      ptr3 = iArr2;
+
+      ncpyPost[0].mode = CK_BUFFER_UNREG;
+      ncpyPost[1].mode = CK_BUFFER_UNREG;
+    }
+
+    void mixedSend(int n1, int *ptr1, int n2, double *ptr2, int n3, int *ptr3, int n4, double *ptr4){
+      if(thisIndex < numElements/2){
+        compareArray(ptr1, iArr1copy, n1);
+        compareArray(ptr2, dArr1copy, n2); // ptr2 is the same as dArr1
+        compareArray(ptr3, iArr2copy, n3); // ptr3 is the same as iArr2
+        compareArray(ptr4, dArr2copy, n4);
+        DEBUG(ckout<<"["<<CkMyPe()<<"] "<<thisIndex<<"->"<<destIndex<<": Mixed send completed "<<endl;)
+        if(thisIndex == 0)
+          CkPrintf("mixedSend: completed\n");
+        thisProxy[thisIndex].sdagRun();
+      }
+      else{
+        // copy the non-zerocopy arrays
+        copyArray(iArr1, ptr1, n1);
+        copyArray(dArr2, ptr4, n4);
+
+        allocateAndCopyArray(iArr1copy, iArr1, n1);
+        allocateAndCopyArray(dArr2copy, dArr2, n4);
+
+        thisProxy[destIndex].mixedSend(n1, iArr1, n2, CkSendBuffer(dArr1, cb, CK_BUFFER_UNREG), n3, CkSendBuffer(iArr2, cb, CK_BUFFER_UNREG), n4, dArr2);
+      }
+    }
+
+    void nextStep() {
+      // reset the completion counters
+      sdagZeroCopyRecvCounter = 0;
+      sdagZeroCopySentCounter = 0;
+
+      if(thisIndex == 0)
+          CkPrintf("sdagRun: Iteration %d completed\n", iter);
+
+      //increase iteration and continue
+      iter++;
+
+      //load balance
+      if(iter % LBPERIOD_ITER == 0)
+        AtSync();
+      else if(iter<= TOTAL_ITER)
+        thisProxy[thisIndex].sdagRun();
+      else {
+        CkCallback reductionCb(CkReductionTarget(Main, done), mainProxy);
+        contribute(reductionCb);
+      }
+    }
+
+    void sdagRecv(int iter, int &n1, int *& ptr1, int &n2, double *&ptr2, CkNcpyBufferPost *ncpyPost) {
+      ptr1 = iArr1;
+      ptr2 = dArr2;
+      // NOTE: The same arrays are used to receive the data for all the 'num' sdag iterations and
+      // the 'TOTAL_ITER' application iterations. This is entirely for the purpose of demonstration
+      // and results in the same array being overwritten. It is important to note that messages can
+      // be out of order and this could cause correctness issues in real applications if the receiver
+      // doesn't receive the arrays correctly.
+      ncpyPost[0].mode = CK_BUFFER_UNREG;
+      ncpyPost[1].mode = CK_BUFFER_UNREG;
+    }
+
+    void ResumeFromSync() {
+      thisProxy[thisIndex].sdagRun();
+    }
+};
+
+#include "simpleZeroCopy.def.h"
diff --git a/examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/simpleZeroCopy.ci b/examples/charm++/zerocopy/entry_method_post_api/unreg/simpleZeroCopy/simpleZeroCopy.ci
new file mode 100644 (file)
index 0000000..4101541
--- /dev/null
@@ -0,0 +1,50 @@
+mainmodule simpleZeroCopy {
+
+  readonly int numElements;
+
+  mainchare Main {
+    entry Main(CkArgMsg *m);
+    entry [reductiontarget] void done();
+  };
+
+  array [1D] zerocopyObject{
+    entry zerocopyObject();
+    entry void testZeroCopy(CProxy_Main mProxy);
+    entry void zerocopySent(CkDataMsg *msg);
+    entry void send(int n1, int ptr1[n1], int n2, double ptr2[n2], int n3, char ptr3[n3]);
+    entry void zerocopySend(int n1, nocopypost int ptr1[n1], int n2, nocopypost double ptr2[n2], int n3, nocopypost char ptr3[n3]);
+    entry void mixedSend(int n1, int ptr1[n1], int n2, nocopypost double ptr2[n2], int n3, nocopypost int ptr3[n3], int n4, double ptr4[n4]);
+
+    entry void sdagRun() {
+      serial {
+        // send num arrays to its partner
+        for(int i = 1; i <= num; i++)
+          thisProxy[destIndex].sdagRecv(iter, iSize1, CkSendBuffer(iArr1copy, sdagCb, CK_BUFFER_UNREG), dSize2, CkSendBuffer(dArr2copy, sdagCb, CK_BUFFER_UNREG));
+      }
+
+      // wait for num arrays from partner
+      for (j = 1; j <= num; j++){
+        when sdagRecv[iter] (int iter, int n1, nocopypost int ptr1[n1], int n2, nocopypost double ptr2[n2]){
+
+          serial {
+
+            //CmiPrintf("[%d][%d][%d] sdagRecv actual method %p, %p and received are %p, %p\n", CmiMyPe(), CmiMyNode(), CmiMyRank(), iArr1, dArr2, ptr1, ptr2);
+            // increment counter on receiving a sdagRecv
+            sdagZeroCopyRecvCounter++;
+            compareArray(iArr1, iArr1copy, n1);
+            compareArray(dArr2, dArr2copy, n2);
+
+            // check that all sends and recvs have completed and then advance
+            //CmiPrintf("[%d][%d][%d] SdagRun recvcounter=%d, sentcounter=%d, num=%d\n", CmiMyPe(), CmiMyNode(), CmiMyRank(), sdagZeroCopyRecvCounter, sdagZeroCopySentCounter, num);
+            if(sdagZeroCopySentCounter == 2*num && sdagZeroCopyRecvCounter == num)
+              nextStep();
+          }
+        }
+      }
+    }
+
+    entry void sdagZeroCopySent(CkDataMsg *msg);
+    entry void sdagRecv(int iter, int n1, nocopypost int ptr1[n1], int n2, nocopypost double ptr2[n2]);
+  };
+
+}