modularize core prof correctly, starting mem pool strat for task records
authorjjenista <jjenista>
Thu, 16 Sep 2010 21:54:42 +0000 (21:54 +0000)
committerjjenista <jjenista>
Thu, 16 Sep 2010 21:54:42 +0000 (21:54 +0000)
Robust/src/Benchmarks/oooJava/sor/makefile
Robust/src/IR/Flat/BuildCode.java
Robust/src/Runtime/memPool.h [new file with mode: 0644]
Robust/src/Runtime/mlp_lock.h

index d1de74d317a290bbcd2f49b81a209f4b193238ba..d944c4449148ecbb8b7b5bc3a0a783ff4300a180 100644 (file)
@@ -5,7 +5,7 @@ SOURCE_FILES=JGFSORBenchSizeD.java
 BUILDSCRIPT=../../../buildscript
 
 USEOOO= -ooojava 24 2  -ooodebug  
-BSFLAGS= -64bit -mainclass $(PROGRAM)  -heapsize-mb 1024 -garbagestats -debug -joptimize -noloop -optimize -coreprof -coreprof-eventwords 1024*1024*128 -coreprof-checkoverflow 
+BSFLAGS= -64bit -mainclass $(PROGRAM)  -heapsize-mb 1024 -garbagestats -debug -joptimize -noloop -optimize -coreprof -coreprof-eventwords 1024*1024*128 #-coreprof-checkoverflow 
 DISJOINT= -disjoint -disjoint-k 1 -enable-assertions #-disjoint-desire-determinism
 
 default:
index 6f002a13b3a1280f92e70ae01975e14b59939f5c..0e5922309ccf4ca8c922b02d041cd4d0c94a45f2 100644 (file)
@@ -78,6 +78,7 @@ public class BuildCode {
   PrefetchAnalysis pa;
   MLPAnalysis mlpa;
   OoOJavaAnalysis oooa;
+  String maxTaskRecSizeStr="__maxTaskRecSize___";
   String mlperrstr = "if(status != 0) { "+
     "sprintf(errmsg, \"MLP error at %s:%d\", __FILE__, __LINE__); "+
     "perror(errmsg); exit(-1); }";
@@ -214,6 +215,11 @@ public class BuildCode {
       outmethodheader.println("#include <string.h>");
       outmethodheader.println("#include \"mlp_runtime.h\"");
       outmethodheader.println("#include \"psemaphore.h\"");
+      outmethodheader.println("#include \"memPool.h\"");
+
+      // spit out a global to inform all worker threads with
+      // the maximum size is for any task record
+      outmethodheader.println("extern int "+maxTaskRecSizeStr+";");
     }
 
     /* Output Structures */
@@ -252,7 +258,7 @@ public class BuildCode {
       outputTaskTypes(outtask);
     }
 
-    if( state.MLP || state.OOOJAVA) {
+    if( state.MLP || state.OOOJAVA) {      
       // have to initialize some SESE compiler data before
       // analyzing normal methods, which must happen before
       // generating SESE internal code
@@ -297,7 +303,7 @@ public class BuildCode {
               //get effect set
               Hashtable<Taint, Set<Effect>>  effects=oooa.getDisjointAnalysis().getEffectsAnalysis().get(fsen);
                     
-              rcr.traverseSESEBlock(fsen, effects, conflicts, rg);
+              //rcr.traverseSESEBlock(fsen, effects, conflicts, rg);
               }
           }
         }
@@ -309,6 +315,10 @@ public class BuildCode {
     // Output function prototypes and structures for SESE's and code
     if( state.MLP || state.OOOJAVA ) {
 
+      // spit out a global to inform all worker threads with
+      // the maximum size is for any task record
+      outmethod.println("int "+maxTaskRecSizeStr+" = 0;");
+
       // used to differentiate, during code generation, whether we are
       // passing over SESE body code, or non-SESE code
       nonSESEpass = false;
@@ -376,7 +386,25 @@ public class BuildCode {
     outmethod.println("  int i;");
 
     if (state.MLP || state.OOOJAVA) {
-      //outmethod.println("  pthread_once( &mlpOnceObj, mlpInitOncePerThread );");
+
+      // do a calculation to determine which task record
+      // is the largest, store that as a global value for
+      // allocating records
+      Iterator<FlatSESEEnterNode> seseit;
+      if(state.MLP){
+        seseit=mlpa.getAllSESEs().iterator();
+      }else{
+        seseit=oooa.getAllSESEs().iterator();
+      }      
+      while(seseit.hasNext()){
+        FlatSESEEnterNode fsen = seseit.next();
+        outmethod.println("if( sizeof( "+fsen.getSESErecordName()+
+                          " ) > "+maxTaskRecSizeStr+
+                          " ) { "+maxTaskRecSizeStr+
+                          " = sizeof( "+fsen.getSESErecordName()+
+                          " ); }" );
+      }
+      
 
       outmethod.println("  workScheduleInit( "+state.MLP_NUMCORES+", invokeSESEmethod );");
       
@@ -549,6 +577,11 @@ public class BuildCode {
     outmethod.println("#include \"methodheaders.h\"");
     outmethod.println("#include \"virtualtable.h\"");
     outmethod.println("#include \"runtime.h\"");
+
+    // always include: compiler directives will leave out
+    // instrumentation when option is not set
+    outmethod.println("#include \"coreprof/coreprof.h\"");
+
     if (state.SANDBOX) {
       outmethod.println("#include \"sandboxdefs.c\"");
     }
@@ -582,9 +615,6 @@ public class BuildCode {
         outmethod.println("#include \"RuntimeConflictResolver.h\"");
       }
     }
-    if (state.COREPROF) {
-      outmethod.println("#include \"coreprof.h\"");
-    }
 
     //Store the sizes of classes & array elements
     generateSizeArray(outmethod);
@@ -2380,8 +2410,9 @@ public class BuildCode {
     // initialize thread-local var to a non-zero, invalid address
     output.println("   seseCaller = (SESEcommon*) 0x2;");
 
-
-    output.println("   CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_BEGIN );");
+    if( state.COREPROF ) {
+      output.println("   CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_BEGIN );");
+    }
 
     HashSet<FlatNode> exitset=new HashSet<FlatNode>();
     exitset.add(seseExit);    
@@ -2426,10 +2457,8 @@ public class BuildCode {
           (state.OOOJAVA && fsen.equals( oooa.getMainSESE() ))
       ) {
        outmethod.println(  "      /* work scheduler works forever, explicitly exit */");
-       if (state.COREPROF) {
-         outmethod.println("      CP_EXIT();");
-         outmethod.println("      CP_DUMP();");
-       }
+        outmethod.println(  "      CP_EXIT();");
+        outmethod.println(  "      CP_DUMP();");       
         outmethod.println(  "      workScheduleExit();");
        outmethod.println(  "      exit( 0 );");
       }
@@ -2855,7 +2884,9 @@ public class BuildCode {
 
          output.println("   {");
          output.println("     SESEcommon* common = (SESEcommon*) "+pair+";");
-          //output.println("     CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_BEGIN );");
+          if( state.COREPROF ) {
+            //output.println("     CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_BEGIN );");
+          }
          output.println("     pthread_mutex_lock( &(common->lock) );");
          output.println("     while( common->doneExecuting == FALSE ) {");
          output.println("       pthread_cond_wait( &(common->doneCond), &(common->lock) );");
@@ -2878,8 +2909,9 @@ public class BuildCode {
            output.println("       "+generateTemp( fmContext, td, null )+
                           " = child->"+vst.getAddrVar().getSafeSymbol()+";");
          }
-
-          //output.println("     CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_END );");
+          if( state.COREPROF ) {
+            //output.println("     CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_END );");
+          }
          output.println("   }");
        }
   
@@ -2892,7 +2924,9 @@ public class BuildCode {
          // otherwise the dynamic write nodes will have the local var up-to-date
          output.println("   {");
          output.println("     if( "+dynVar+"_srcSESE != NULL ) {");
-          //output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_BEGIN );");
+          if( state.COREPROF ) {
+            //output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_BEGIN );");
+          }
          output.println("       SESEcommon* common = (SESEcommon*) "+dynVar+"_srcSESE;");
          output.println("       psem_take( &(common->stallSem) );");
 
@@ -2916,7 +2950,9 @@ public class BuildCode {
          output.println("       "+generateTemp( fmContext, dynVar, null )+
                          " = *(("+typeStr+"*) ("+
                          dynVar+"_srcSESE + "+dynVar+"_srcOffset));");
-          //output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_END );");
+          if( state.COREPROF ) {
+            //output.println("       CP_LOGEVENT( CP_EVENTID_TASKSTALLVAR, CP_EVENTTYPE_END );");
+          }
          output.println("     }");
          output.println("   }");
        }
@@ -2984,9 +3020,13 @@ public class BuildCode {
                 output.println("     rentry->queue=seseCaller->memoryQueueArray["+ waitingElement.getQueueID()+ "];");
                 output.println("     if(ADDRENTRY(seseCaller->memoryQueueArray["+ waitingElement.getQueueID()
                            + "],rentry)==NOTREADY){");
-                //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
+                if( state.COREPROF ) {
+                  //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
+                }
                 output.println("        psem_take( &(rentry->parentStallSem) );");
-                //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_END );");
+                if( state.COREPROF ) {
+                  //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_END );");
+                }
                 output.println("     }  ");
                 
                 if(state.RCR && rcr != null) {
@@ -3032,9 +3072,13 @@ public class BuildCode {
                   output
                     .println("     if(ADDRENTRY(seseCaller->memoryQueueArray["+ waitingElement.getQueueID()
                              + "],rentry)==NOTREADY){");
-                  //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
+                  if( state.COREPROF ) {
+                    //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_BEGIN );");
+                  }
                   output.println("        psem_take( &(rentry->parentStallSem) );");
-                  //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_END );");
+                  if( state.COREPROF ) {
+                    //output.println("        CP_LOGEVENT( CP_EVENTID_TASKSTALLMEM, CP_EVENTTYPE_END );");
+                  }
                   output.println("     }  ");
                 }
                 output.println("   }");
@@ -3573,8 +3617,9 @@ public class BuildCode {
 
     output.println("   {");
 
-
-    output.println("CP_LOGEVENT( CP_EVENTID_TASKDISPATCH, CP_EVENTTYPE_BEGIN );");
+    if( state.COREPROF ) {
+      output.println("CP_LOGEVENT( CP_EVENTID_TASKDISPATCH, CP_EVENTTYPE_BEGIN );");
+    }
 
     // set up the parent
     if( (state.MLP && fsen == mlpa.getMainSESE()) || 
@@ -4078,8 +4123,9 @@ public class BuildCode {
     // eventually, for it to mark itself finished
 //    output.println("     pthread_mutex_unlock( &(seseToIssue->common.lock) );");
 
-
-    output.println("CP_LOGEVENT( CP_EVENTID_TASKDISPATCH, CP_EVENTTYPE_END );");
+    if( state.COREPROF ) {
+      output.println("CP_LOGEVENT( CP_EVENTID_TASKDISPATCH, CP_EVENTTYPE_END );");
+    }
 
     output.println("   }");
     
@@ -4111,11 +4157,16 @@ public class BuildCode {
     if( fsen.getIsCallerSESEplaceholder() ) {
       return;
     }
-
-    output.println("   CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_END );");
+    
+    if( state.COREPROF ) {
+      output.println("   CP_LOGEVENT( CP_EVENTID_TASKEXECUTE, CP_EVENTTYPE_END );");
+    }
 
     output.println("   /* SESE exiting */");
-    output.println("   CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_BEGIN );");
+
+    if( state.COREPROF ) {
+      output.println("   CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_BEGIN );");
+    }
     
     String com = paramsprefix+"->common";
 
@@ -4252,8 +4303,9 @@ public class BuildCode {
     // calls to a non-zero, invalid address
     output.println("   seseCaller = (SESEcommon*) 0x1;");    
 
-
-    output.println("   CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_END );");
+    if( state.COREPROF ) {
+      output.println("   CP_LOGEVENT( CP_EVENTID_TASKRETIRE, CP_EVENTTYPE_END );");
+    }
   }
  
   public void generateFlatWriteDynamicVarNode( FlatMethod fm,  
diff --git a/Robust/src/Runtime/memPool.h b/Robust/src/Runtime/memPool.h
new file mode 100644 (file)
index 0000000..ffd665c
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef ___MEMPOOL_H__
+#define ___MEMPOOL_H__
+
+//////////////////////////////////////////////////////////
+//
+//  A memory pool implements POOLCREATE, POOLALLOC and 
+//  POOLFREE to improve memory allocation by reusing records.
+//
+//  This implementation uses a lock-free singly-linked list
+//  to store reusable records.  The list is initialized with
+//  one valid record, and the list is considered empty when
+//  it has only one record; this allows the enqueue operation's
+//  CAS to assume tail can always be dereferenced.
+//
+//  poolfree adds newly freed records to the list BACK
+//
+//  poolalloc either takes records from FRONT or mallocs
+//
+//////////////////////////////////////////////////////////
+
+#include <stdlib.h>
+#include "mlp_lock.h"
+
+
+// The cache line size is set for the AMD Opteron 6168 (dc-10)
+// that has L1 and L2 cache line sizes of 64 bytes.  Source:
+// http://www.cs.virginia.edu/~skadron/cs451/opteron/opteron.ppt
+#define CACHELINESIZE 64
+
+
+typedef struct MemPoolItem_t {
+  void* next;
+} MemPoolItem;
+
+
+typedef struct MemPool_t {
+  int itemSize;
+  MemPoolItem* head;
+
+  // avoid cache line contention between producer/consumer...
+  char buffer[CACHELINESIZE - sizeof(void*)];
+
+  MemPoolItem* tail;
+} MemPool;
+
+
+// the memory pool must always have at least one
+// item in it
+static MemPool* poolcreate( int itemSize ) {
+  MemPool* p    = malloc( sizeof( MemPool ) );
+  p->itemSize   = itemSize;
+  p->head       = malloc( itemSize );
+  p->head->next = NULL;
+  p->tail       = p->head;
+}
+
+
+// CAS
+// in: a ptr, expected old, desired new
+// return: actual old
+//
+// Pass in a ptr, what you expect the old value is and
+// what you want the new value to be.
+// The CAS returns what the value is actually: if it matches
+// your proposed old value then you assume the update was successful,
+// otherwise someone did CAS before you, so try again (the return
+// value is the old value you will pass next time.)
+
+static inline void poolfree( MemPool* p, void* ptr ) {
+
+  MemPoolItem* tailCurrent;
+  MemPoolItem* tailActual;
+  
+  // set up the now unneeded record to as the tail of the
+  // free list by treating its first bytes as next pointer,
+  MemPoolItem* tailNew = (MemPoolItem*) ptr;
+  tailNew->next = NULL;
+
+  while( 1 ) {
+    // make sure the null happens before the insertion,
+    // also makes sure that we reload tailCurrent, etc..
+    BARRIER();
+
+    tailCurrent = p->tail;
+    tailActual = (MemPoolItem*)
+      CAS( &(p->tail),         // ptr to set
+           (long) tailCurrent, // current tail's next should be NULL
+           (long) tailNew      // try set to our new tail
+           );   
+    if( tailActual == tailCurrent ) {
+      // success, update tail
+      tailCurrent->next = tailNew;
+      return;
+    }
+
+    // if CAS failed, retry entire operation
+  }
+}
+
+
+static inline void* poolalloc( MemPool* p ) {
+
+  // to protect CAS in poolfree from dereferencing
+  // null, treat the queue as empty when there is
+  // only one item.  The dequeue operation is only
+  // executed by the thread that owns the pool, so
+  // it doesn't require an atomic op
+  MemPoolItem* headCurrent = p->head;
+
+  if( headCurrent->next == NULL ) {
+    // only one item, so don't take from pool
+    return calloc( 1, p->itemSize );
+  }
+  p->head = headCurrent->next;
+  return headCurrent;
+}
+
+
+#endif // ___MEMPOOL_H__
+
+
+
+
+
+
+
+
+
+
index b1bea4ba3605841c2f6196f4f8285c77f1f61bff..0550a9c30a18943faab2acb39c4860314bca67bc 100644 (file)
@@ -1,3 +1,7 @@
+#ifndef ____MLP_LOCK_H__
+#define ____MLP_LOCK_H__
+
+
 #include "runtime.h"
 
 #include <stdlib.h>
@@ -94,3 +98,6 @@ static inline int BARRIER(){
   CFENCE;
   return 1;
 }
+
+
+#endif // ____MLP_LOCK_H__