c++ - How to use a openvdb (parallel) foreach accessing multiple grids? -
i have openvdb grid iterate using functor , openvdb::tools::foreach.
//the grid iterating on grid g; //the operator used update each single voxel of g struct functor{ inline void operator()(const grid::valueonciter& iter) const { } };
if operation involved g have called
functor op; openvdb::tools::foreach(visiblegrid->cbeginvalueon(), op, true, true);
at each voxel (iteration) though need access , modify additional grid(s) based on computed value of iteration step.
my inital solution involved providing functor accessor of additional grid(s):
struct functor{ grid2::accessor grid2_accessor; functor( grid2::accessor& a) : grid2_accessor(a){} inline void operator()(const grid::valueonciter& iter) const { //use grid2_accessor based on iter.getcoord() } };
the accessor provided functor @ construction time , each thread of parallel copy of functor:
functor op(g2->getaccessor() ); openvdb::tools::foreach(g1->cbeginvalueon(), op, true, **false**);
unfortunately solution not work since:
- the accessor must not const accessed
- but functor::operator() must const method used tools::foreach
a second dirty solution declare functor accessor copy mutable. solution not work in debug due openvdb assertion failing (most memory leak).
is there solution problem? e.g. tools::foreach not require operator() const.
it not safe use same valueaccessor
in different threads. instead, want have unique valueaccessor
s each thread share underlying tree.
define functor
instead:
struct functor { grid2& mgrid2; functor(grid2& grid2) : mgrid2(grid2) {} void operator()(const grid::valueonciter& iter) const { grid2::accessor grid2acc(grid2.getaccessor()); // allowed because grid2 reference // want } }
the reason can't find non-const version of operator because underlying implementation relies on tbb
. motivation give in tbb documentation is:
because body object might copied, operator() should not modify body. otherwise modification might or might not become visible thread invoked parallel_for, depending upon whether operator() acting on original or copy. reminder of nuance, parallel_for requires body object's operator() declared const.
because of should not expect non-const version time soon.
edit: noted in comments possible reuse cache in valueaccessor
. however, member of class have problem modify tree using in operator (as setvalue
non-const). if know no 1 else writing same memory place can small hack:
struct functor { grid2::valueaccessor mgrid2acc; functor(grid2::valueaccessor grid2acc) : mgrid2acc(grid2acc) {} void operator()(const grid::valueonciter& iter) const { const grid2::valuetype& v = mgrid2acc.getvalue(iter.getcoord()); grid2::valuetype& non_const_v = const_cast<grid2::valuetype&>(v); // modify value please, race condition occur // if more 1 thread write same location } }
i still prefer first solution. can cache leaf node calling probeleaf(openvdb::coord& ijk)
on accessor.
Comments
Post a Comment