[RFC] PatchFunction cleanup/extension
Richard Guenther
rguenth at tat.physik.uni-tuebingen.de
Wed Jan 8 13:49:08 UTC 2003
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()
More information about the pooma-dev
mailing list