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 valueaccessors 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

Popular posts from this blog

magento2 - Magento 2 admin grid add filter to collection -

Android volley - avoid multiple requests of the same kind to the server? -

Combining PHP Registration and Login into one class with multiple functions in one PHP file -