freepooma-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC] PatchFunction cleanup/extension


From: Richard Guenther
Subject: [RFC] PatchFunction cleanup/extension
Date: Wed, 8 Jan 2003 14:49:08 +0100 (CET)

Hi!

I'm in the beginning of cleaning up PatchFunction and make it do what
I need. I stumbled over the DataObjectRequest<> object and wonder, if
the order of requesting read and write locks matter? I.e. is

   DataObjectRequest<WriteRequest> writeReq(*this);
   engineFunctor(engine1,writeReq);
   DataObjectRequest<ReadRequest> readReq(writeReq);
   engineFunctor(engine2,readReq);

the same as

   DataObjectRequest<WriteRequest> writeReq(*this);
   DataObjectRequest<ReadRequest> readReq(writeReq);
   engineFunctor(engine2,readReq);
   engineFunctor(engine1,writeReq);

?

A little cleanup of PatchFunction/PatchKernel sofar brought control
over read/write attributes of PatchTag type operations, like the
ParticleTags and reduces the number of sourcelines by using overloads
rather than partial specializations for the PatchEvaluator<> class.

Is this sound? Other Comments?

Richard.

Oh - in the near future I need about 5-7 arrays I can operate on with
PatchFunction<> and support for Remote MultiPatch engines, too. If we
only had a "real" preprocessor...


===== PatchFunction.h 1.2 vs edited =====
--- 1.2/r2/src/Evaluator/PatchFunction.h        Thu Dec 19 10:37:26 2002
+++ edited/PatchFunction.h      Wed Jan  8 14:40:02 2003
@@ -36,32 +36,11 @@

 //////////////////////////////////////////////////////////////////////

-//-----------------------------------------------------------------------------
-// Overview:
-//
-// PatchFunction is mix-in class that encapsulates evaluation of patch-based
-// functors in parallel.
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// Typedefs:
-//-----------------------------------------------------------------------------
-
-//-----------------------------------------------------------------------------
-// Includes:
-//-----------------------------------------------------------------------------
-
-#include "PETE/PETE.h"
-#include "Pooma/PETE/AssertEquals.h"
-#include "Evaluator/EvaluatorTags.h"
-#include "Evaluator/Evaluator.h"
-#include "Evaluator/PatchKernel.h"
-#include "Engine/EnginePatch.h"
-#include "Threads/PoomaCSem.h"
-
-//-----------------------------------------------------------------------------
-//
-// Full Description:
+/** @file
+ * @ingroup Evaluator
+ * @brief
+ * PatchFunction is mix-in class that encapsulates evaluation of patch-based
+ * functors in parallel.
 //
 // PatchFunctions are tools that allow you to apply a functor to the patches
 // in an array in parallel.  For example, you could write a functor:
@@ -89,20 +68,55 @@
 // Constructor arguments are passed to the constructor of a functor object
 // of type Functor.  Tag is a policy tag specifying the type of action
 // performed.  Currently the following tags are supported:
-//
+*/
+
+//-----------------------------------------------------------------------------
+// Typedefs:
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Includes:
 //-----------------------------------------------------------------------------

+#include "PETE/PETE.h"
+#include "Pooma/PETE/AssertEquals.h"
+#include "Evaluator/EvaluatorTags.h"
+#include "Evaluator/Evaluator.h"
+#include "Evaluator/PatchKernel.h"
+#include "Engine/EnginePatch.h"
+#include "Threads/PoomaCSem.h"
+
+
 //-----------------------------------------------------------------------------
 // Policy tags for patch functions.
-//
-// PatchParticleN - recommended for operations on particles, bypasses the
-//                  intersection process and just loops through the patches.
 //-----------------------------------------------------------------------------

-struct PatchTag1 { };
-struct PatchReadTag1 { };
-struct PatchTag2 { };
-struct PatchTag3 { };
+// Patch tags that include intersection process.
+
+template <bool Write1>
+struct PatchRWTag1 {
+  enum { write1 = Write1,
+        any = Write1 };
+};
+template <bool Write1, bool Write2>
+struct PatchRWTag2 {
+  enum { write1 = Write1, write2 = Write2,
+        any = Write1 || Write2 };
+};
+template <bool Write1, bool Write2, bool Write3>
+struct PatchRWTag3 {
+  enum { write1 = Write1, write2 = Write2, write3 = Write3,
+        any = Write1 || Write2 || Write3 };
+};
+
+// Backward compatibility typedefs.
+typedef PatchRWTag1<true> PatchTag1;
+typedef PatchRWTag1<false> PatchReadTag1;
+typedef PatchRWTag2<true, false> PatchTag2;
+typedef PatchRWTag3<true, false, false> PatchTag3;
+
+// PatchParticleN - recommended for operations on particles, bypasses the
+//                  intersection process and just loops through the patches.

 template<bool Write1>
 struct PatchParticle1 { };
@@ -134,31 +148,16 @@

   ~PatchEvaluator() {}

-  template<class A1, class Function>
+  template<class ReadWriteTag, class A1, class Function>
   void evaluate(const A1& a1, const Function& function) const
   {
-    typedef typename EvaluatorTag1<A1>::Evaluator_t Evaluator_t;
-    PatchEvaluator<Evaluator_t> evaluator;
-    Pooma::Scheduler_t &scheduler = Pooma::scheduler();
-    scheduler.beginGeneration();
-    evaluator.evaluate(a1(), function);
-    notifyEngineWrite(a1.engine());
-    scheduler.endGeneration();
-
-    if (Pooma::blockingExpressions())
-    {
-      Pooma::blockAndEvaluate();
-    }
-  }
-
-  template<class A1, class Function>
-  void evaluateRead(const A1& a1, const Function& function) const
-  {
-    typedef typename EvaluatorTag1<A1>::Evaluator_t Evaluator_t;
-    PatchEvaluator<Evaluator_t> evaluator;
+    typedef typename EvaluatorTag1<A1>::Evaluator_t Eval_t;
+    PatchEvaluator<Eval_t> evaluator;
     Pooma::Scheduler_t &scheduler = Pooma::scheduler();
     scheduler.beginGeneration();
-    evaluator.evaluateRead(a1(), function);
+    evaluator.evaluate<ReadWriteTag>(a1(), function);
+    if (ReadWriteTag::write1)
+      notifyEngineWrite(a1.engine());
     scheduler.endGeneration();

     if (Pooma::blockingExpressions())
@@ -167,16 +166,19 @@
     }
   }

-  template<class A1,class A2,class Function>
-  void evaluate2(const A1& a1, const A2& a2,
+  template<class ReadWriteTag, class A1,class A2,class Function>
+  void evaluate(const A1& a1, const A2& a2,
                const Function& function) const
   {
     typedef typename EvaluatorTag<A1,A2>::Evaluator_t Eval_t;
     PatchEvaluator<Eval_t> evaluator;
     Pooma::Scheduler_t &scheduler = Pooma::scheduler();
     scheduler.beginGeneration();
-    evaluator.evaluate2(a1(), a2(), function);
-    notifyEngineWrite(a1.engine());
+    evaluator.evaluate<ReadWriteTag>(a1(), a2(), function);
+    if (ReadWriteTag::write1)
+      notifyEngineWrite(a1.engine());
+    if (ReadWriteTag::write2)
+      notifyEngineWrite(a2.engine());
     scheduler.endGeneration();

     if (Pooma::blockingExpressions())
@@ -185,8 +187,8 @@
     }
   }

-  template<class A1, class A2, class A3, class Function>
-  void evaluate3(const A1& a1, const A2& a2, const A3 &a3,
+  template<class ReadWriteTag, class A1, class A2, class A3, class Function>
+  void evaluate(const A1& a1, const A2& a2, const A3 &a3,
                const Function& function) const
   {
     typedef typename EvaluatorTag1<A2>::Evaluator_t Eval2_t;
@@ -198,8 +200,13 @@
     PatchEvaluator<Eval_t> evaluator;
     Pooma::Scheduler_t &scheduler = Pooma::scheduler();
     scheduler.beginGeneration();
-    evaluator.evaluate3(a1(), a2(), a3(), function);
-    notifyEngineWrite(a1.engine());
+    evaluator.evaluate<ReadWriteTag>(a1(), a2(), a3(), function);
+    if (ReadWriteTag::write1)
+      notifyEngineWrite(a1.engine());
+    if (ReadWriteTag::write2)
+      notifyEngineWrite(a2.engine());
+    if (ReadWriteTag::write3)
+      notifyEngineWrite(a3.engine());
     scheduler.endGeneration();

     if (Pooma::blockingExpressions())
@@ -231,37 +238,29 @@
   //
   ~PatchEvaluator() {}

-  template<class A1, class Function>
+  template<class ReadWriteTag, class A1, class Function>
   void evaluate(const A1& a1, const Function& function) const
   {
-    Pooma::Iterate_t *iterate = new PatchKernel<A1,Function>(a1,function);
-    Pooma::scheduler().handOff(iterate);
-  }
-
-  template<class A1, class Function>
-  void evaluateRead(const A1& a1, const Function& function) const
-  {
-    Pooma::Iterate_t *iterate = new PatchKernel<A1,Function>(a1,function);
+    Pooma::Iterate_t *iterate =
+      new PatchKernel<ReadWriteTag,A1,Function>(a1,function);
     Pooma::scheduler().handOff(iterate);
   }

-  template<class A1,class A2,class Function>
-  void evaluate2(const A1 &a1, const A2 &a2,
+  template<class ReadWriteTag, class A1,class A2,class Function>
+  void evaluate(const A1 &a1, const A2 &a2,
                const Function &function) const
   {
     Pooma::Iterate_t *iterate =
-      new PatchKernel2<A1,A2,Function>(a1,a2,function);
-
+      new PatchKernel2<ReadWriteTag,A1,A2,Function>(a1,a2,function);
     Pooma::scheduler().handOff(iterate);
   }

-  template<class A1, class A2, class A3, class Function>
-  void evaluate3(const A1 &a1, const A2 &a2, const A3 &a3,
+  template<class ReadWriteTag, class A1, class A2, class A3, class Function>
+  void evaluate(const A1 &a1, const A2 &a2, const A3 &a3,
                const Function &function) const
   {
     Pooma::Iterate_t *iterate =
-      new PatchKernel3<A1,A2,A3,Function>(a1,a2,a3,function);
-
+      new PatchKernel3<ReadWriteTag,A1,A2,A3,Function>(a1,a2,a3,function);
     Pooma::scheduler().handOff(iterate);
   }

@@ -290,7 +289,7 @@
   //
   ~PatchEvaluator() {}

-  template<class A1,class Function>
+  template<class ReadWriteTag, class A1,class Function>
   void evaluate(const A1& a1,const Function& function) const
   {
     typedef Intersector<A1::dimensions> Inter_t;
@@ -301,20 +300,14 @@
     typename Inter_t::const_iterator i = inter.begin();
     while (i != inter.end())
     {
-      PatchEvaluator<SinglePatchEvaluatorTag>().evaluate(a1(*i),function);
+      PatchEvaluator<SinglePatchEvaluatorTag>().
+       evaluate<ReadWriteTag>(a1(*i),function);
       ++i;
     }
   }

-  template<class A1,class Function>
-  inline
-  void evaluateRead(const A1& a1,const Function& function) const
-  {
-    evaluate(a1,function);
-  }
-
-  template<class A1,class A2,class Function>
-  void evaluate2(const A1& a1, const A2& a2,
+  template<class ReadWriteTag, class A1,class A2,class Function>
+  void evaluate(const A1& a1, const A2& a2,
                const Function& function) const
   {
     typedef Intersector<A1::dimensions> Inter_t;
@@ -326,16 +319,15 @@
     typename Inter_t::const_iterator i = inter.begin();
     while (i != inter.end())
     {
-      PatchEvaluator<SinglePatchEvaluatorTag>().evaluate2(a1(*i), a2(*i),
-                                                         function
-                                                         );
+      PatchEvaluator<SinglePatchEvaluatorTag>().
+       evaluate<ReadWriteTag>(a1(*i), a2(*i), function);
       ++i;
     }
   }

-  template<class A1, class A2, class A3, class Function>
-  void evaluate3(const A1 &a1, const A2 &a2, const A3 &a3,
-                const Function& function) const
+  template<class ReadWriteTag, class A1, class A2, class A3, class Function>
+  void evaluate(const A1 &a1, const A2 &a2, const A3 &a3,
+               const Function& function) const
   {
     typedef Intersector<A1::dimensions> Inter_t;
     Inter_t inter;
@@ -348,7 +340,7 @@
     while (i != inter.end())
     {
       PatchEvaluator<SinglePatchEvaluatorTag>().
-        evaluate3(a1(*i), a2(*i), a3(*i), function);
+        evaluate<ReadWriteTag>(a1(*i), a2(*i), a3(*i), function);
       ++i;
     }
   }
@@ -651,38 +643,9 @@
 { }


-template<class Function, class Patch>
+template<class Function, class ReadWriteTag>
 class PatchFunction
 {
-};
-
-template<class Function>
-class PatchFunction<Function,PatchTag1>
-{
-public:
-
-  PatchFunction() { }
-  PatchFunction(const Function &function) : function_m(function) { }
-
-  POOMA_PATCHFUNCTION_ARGUMENT_CONSTRUCTORS(PatchFunction,function_m)
-
-  template<class Array>
-  inline void
-  operator()(const Array& a) const
-  {
-    PatchEvaluator<MainEvaluatorTag>().evaluate(a,function());
-  }
-
-  inline const Function &function() const { return function_m; }
-
-private:
-
-  Function function_m;
-};
-
-template<class Function>
-class PatchFunction<Function,PatchReadTag1>
-{
 public:

   PatchFunction() { }
@@ -690,57 +653,25 @@

   POOMA_PATCHFUNCTION_ARGUMENT_CONSTRUCTORS(PatchFunction,function_m)

-  template<class Array>
+  template<class Array1>
   inline void
-  operator()(const Array& a) const
+  operator()(const Array1& a) const
   {
-    PatchEvaluator<MainEvaluatorTag>().evaluateRead(a,function());
+    PatchEvaluator<MainEvaluatorTag>().evaluate<ReadWriteTag>(a,function());
   }

-  inline const Function &function() const { return function_m; }
-
-private:
-
-  Function function_m;
-};
-
-template<class Function>
-class PatchFunction<Function,PatchTag2>
-{
-public:
-  PatchFunction() { }
-  PatchFunction(const Function &function) : function_m(function) { }
-
-  POOMA_PATCHFUNCTION_ARGUMENT_CONSTRUCTORS(PatchFunction,function_m)
-
   template<class Array1, class Array2>
   inline void
   operator()(const Array1 &a1, const Array2 &a2) const
   {
-    PatchEvaluator<MainEvaluatorTag>().evaluate2(a1,a2,function());
+    
PatchEvaluator<MainEvaluatorTag>().evaluate<ReadWriteTag>(a1,a2,function());
   }

-  inline const Function &function() const { return function_m; }
-
-private:
-
-  Function function_m;
-};
-
-template<class Function>
-class PatchFunction<Function,PatchTag3>
-{
-public:
-  PatchFunction() { }
-  PatchFunction(const Function &function) : function_m(function) { }
-
-  POOMA_PATCHFUNCTION_ARGUMENT_CONSTRUCTORS(PatchFunction,function_m)
-
   template<class Array1, class Array2, class Array3>
   inline void
   operator()(const Array1 &a1, const Array2 &a2, const Array3 &a3) const
   {
-    PatchEvaluator<MainEvaluatorTag>().evaluate3(a1,a2,a3,function());
+    
PatchEvaluator<MainEvaluatorTag>().evaluate<ReadWriteTag>(a1,a2,a3,function());
   }

   inline const Function &function() const { return function_m; }
===== PatchKernel.h 1.2 vs edited =====
--- 1.2/r2/src/Evaluator/PatchKernel.h  Thu Dec 19 10:37:26 2002
+++ edited/PatchKernel.h        Wed Jan  8 14:40:02 2003
@@ -36,11 +36,12 @@

 //////////////////////////////////////////////////////////////////////

-//-----------------------------------------------------------------------------
-// Overview:
-// A PatchKernel encapsulates performing operations on a patch of an
-// expression.
-//-----------------------------------------------------------------------------
+/** @file
+ * @ingroup Evaluator
+ * @brief
+ * A PatchKernel encapsulates performing operations on a patch of an
+ * expression.
+ */

 //-----------------------------------------------------------------------------
 // Typedefs:
@@ -63,30 +64,28 @@
 // Forward Declarations:
 //-----------------------------------------------------------------------------

-template<class A1,class Function>
+template<class ReadWriteTag, class A1,class Function>
 class PatchKernel
   : public Pooma::Iterate_t
 {
 public:
-  PatchKernel(const A1& a1, const Function& function, bool write = true)
+  PatchKernel(const A1& a1, const Function& function)
     : Pooma::Iterate_t(Pooma::scheduler()),
-      write_m(write), a1_m(a1), function_m(function)
+      a1_m(a1), function_m(function)
   {
     DataObjectRequest<BlockAffinity> getAffinity;
     hintAffinity(engineFunctor(a1_m.engine(),getAffinity));

     // Request locks
-    // currently we ignore write_m, because I'm not sure if iterates
+    // currently we ignore ReadWriteTag::write1, because I'm not sure if 
iterates
     // will run if they don't have a write lock requested.

     DataObjectRequest<WriteRequest> writeReq(*this);
     engineFunctor(a1_m.engine(),writeReq);
-
   }

   virtual ~PatchKernel()
   {
-
     DataObjectRequest<WriteRelease> writeReq;
     engineFunctor(a1_m.engine(),writeReq);
   }
@@ -97,13 +96,11 @@
   }

 private:
-
-  bool write_m;
   A1 a1_m;
   Function function_m;
 };

-template<class A1, class A2, class Function>
+template<class ReadWriteTag, class A1, class A2, class Function>
 class PatchKernel2
   : public Pooma::Iterate_t
 {
@@ -124,7 +121,10 @@
     // on the right.

     DataObjectRequest<WriteRequest> writeReq(*this);
-    engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write1 || !ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),writeReq);

     // Now make the read request.
     // Use the remembered write request block to check and see
@@ -132,24 +132,32 @@
     // iterated instead of a request of the data object.

     DataObjectRequest<ReadRequest> readReq(writeReq);
-    engineFunctor(a2_m.engine(),readReq);
-  }
+    if (!ReadWriteTag::write1 && ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),readReq);
+    if (!ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),readReq);
+  }

   virtual ~PatchKernel2()
   {
-
     // The write request remembers the data block it sees on the left
     // so that it can check and see if it finds it on the right.

     DataObjectRequest<WriteRelease> writeReq;
-    engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write1 || !ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),writeReq);

     // The read request checks to see if the data object for the left
     // appears on the right.  If it does, it doesn't do a release for it
     // since a request wasn't generated above.

     DataObjectRequest<ReadRelease> readReq(writeReq);
-    engineFunctor(a2_m.engine(),readReq);
+    if (!ReadWriteTag::write1 && ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),readReq);
+    if (!ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),readReq);
   }

   virtual void run()
@@ -158,14 +166,14 @@
   }

 private:
-
   A1 a1_m;
   A2 a2_m;
   Function function_m;
 };

-template<class A1, class A2, class A3, class Function>
-class PatchKernel3 : public Pooma::Iterate_t
+template<class ReadWriteTag, class A1, class A2, class A3, class Function>
+class PatchKernel3
+  : public Pooma::Iterate_t
 {
 public:
   PatchKernel3(const A1 &a1, const A2 &a2, const A3 &a3,
@@ -184,7 +192,12 @@
     // on the right.

     DataObjectRequest<WriteRequest> writeReq(*this);
-    engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write1 || !ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),writeReq);
+    if (ReadWriteTag::write3)
+      engineFunctor(a3_m.engine(),writeReq);

     // Now make the read request.
     // Use the remembered write request block to check and see
@@ -192,8 +205,12 @@
     // iterated instead of a request of the data object.

     DataObjectRequest<ReadRequest> readReq(writeReq);
-    engineFunctor(a2_m.engine(),readReq);
-    engineFunctor(a3_m.engine(),readReq);
+    if (!ReadWriteTag::write1 && ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),readReq);
+    if (!ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),readReq);
+    if (!ReadWriteTag::write2)
+      engineFunctor(a3_m.engine(),readReq);
   }

   virtual ~PatchKernel3()
@@ -202,15 +219,24 @@
     // so that it can check and see if it finds it on the right.

     DataObjectRequest<WriteRelease> writeReq;
-    engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write1 || !ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),writeReq);
+    if (ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),writeReq);
+    if (ReadWriteTag::write3)
+      engineFunctor(a3_m.engine(),writeReq);

     // The read request checks to see if the data object for the left
     // appears on the right.  If it does, it doesn't do a release for it
     // since a request wasn't generated above.

     DataObjectRequest<ReadRelease> readReq(writeReq);
-    engineFunctor(a2_m.engine(),readReq);
-    engineFunctor(a3_m.engine(),readReq);
+    if (!ReadWriteTag::write1 && ReadWriteTag::any)
+      engineFunctor(a1_m.engine(),readReq);
+    if (!ReadWriteTag::write2)
+      engineFunctor(a2_m.engine(),readReq);
+    if (!ReadWriteTag::write3)
+      engineFunctor(a3_m.engine(),readReq);
   }

   virtual void run()

reply via email to

[Prev in Thread] Current Thread [Next in Thread]