32 #ifndef _CnC_REDUCE_H_ 33 #define _CnC_REDUCE_H_ 35 #include <cnc/internal/cnc_stddef.h> 36 #include <cnc/internal/tbbcompat.h> 37 #include <tbb/concurrent_unordered_map.h> 38 #include <tbb/combinable.h> 39 #include <tbb/atomic.h> 40 #include <tbb/spin_rw_mutex.h> 46 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
class reduction;
95 template<
typename Ctxt,
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
104 return new reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >( ctxt, name, in, cnt, out, op, idty, sel );
119 static const char BCASTCOUNT = 93;
120 static const char GATHERCOUNT = 94;
121 static const char DONE = 95;
122 static const char ALLDONE = 96;
123 static const char VALUE = 97;
124 static const char ALLVALUES = 98;
129 static const int LOCAL = 0;
130 static const int CNT_AVAILABLE = 1;
131 static const int BCAST_DONE = 2;
132 static const int FINISH = 3;
133 static const int DONE = 4;
137 # define TRACE( _m ) static std::string _t_n_( m_reduce->name() + _m ); VT_FUNC( _t_n_.c_str() ); 142 #define M1 static_cast< CType >( -1 ) 168 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
176 template<
typename Ctxt >
177 reduction(
CnC::context< Ctxt > & ctxt,
const std::string & name, icoll_type & in, ccoll_type & c, ocoll_type & out,
const ReduceOp & red,
const IType & identity,
const Select & sel );
186 typedef reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select > reduce_type;
187 typedef tbb::spin_rw_mutex mutex_type;
191 tbb::combinable< IType > val;
192 tbb::atomic< CType > nreduced;
193 tbb::atomic< CType > n;
196 tbb::atomic< int > nCounts;
197 tbb::atomic< int > nValues;
201 tbb::atomic< int > status;
203 red_tls(
const IType & v );
204 red_tls(
const red_tls & rt );
206 void operator=(
const red_tls & rt );
208 typedef tbb::concurrent_unordered_map< OTag, red_tls > tls_map_type;
211 struct on_item_put :
public icoll_type::callback_type
213 on_item_put( reduce_type * r );
214 void on_put(
const ITag & tag,
const IType & val );
216 void on_value(
const OTag & otag,
const typename tls_map_type::iterator & i,
const IType & val );
218 void add_value(
const typename tls_map_type::iterator & i,
const IType & val )
const;
221 reduce_type * m_reduce;
223 friend struct on_item_put;
226 struct on_count_put :
public ccoll_type::callback_type
228 on_count_put( reduce_type * r );
229 void on_put(
const OTag & otag,
const CType & cnt );
231 void on_done(
const OTag & otag,
const typename tls_map_type::iterator & i,
const int owner );
232 void on_bcastCount(
const OTag & otag,
const typename tls_map_type::iterator & i,
const CType & cnt,
const int owner );
233 void on_gatherCount(
const OTag & otag,
const typename tls_map_type::iterator & i,
const CType & cnt );
236 reduce_type * m_reduce;
238 friend struct on_count_put;
240 typename tls_map_type::iterator
get(
const OTag & tag );
241 bool try_put_value(
const OTag & otag,
const typename tls_map_type::iterator & i );
243 bool send_count(
const OTag & otag,
const typename tls_map_type::iterator & i,
const int to,
const bool always );
244 static int my_parent_for_root(
const int root );
245 void try_send_or_put_value(
const OTag & otag,
const typename tls_map_type::iterator & i );
246 void try_send_or_put_all();
251 int bcast_count(
const OTag & tag,
const CType & val,
const int root );
257 on_item_put * m_ondata;
258 on_count_put * m_oncount;
261 tls_map_type m_reductions;
262 const IType m_identity;
264 tbb::atomic< int > m_nDones;
272 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
273 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::red_tls::red_tls()
287 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
288 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::red_tls::red_tls(
const IType & v )
303 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
304 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::red_tls::red_tls(
const red_tls & rt )
306 nreduced( rt.nreduced ),
310 nCounts( rt.nCounts ),
311 nValues( rt.nValues ),
320 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
321 template<
typename Ctxt >
322 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::reduction(
CnC::context< Ctxt > & ctxt,
const std::string & name,
323 icoll_type & in, ccoll_type & c, ocoll_type & out,
324 const ReduceOp & red,
const IType & identity,
const Select & sel )
329 m_ondata(
new on_item_put(
this ) ),
330 m_oncount(
new on_count_put(
this ) ),
334 m_identity( identity )
337 m_in.on_put( m_ondata );
338 m_cnt.on_put( m_oncount );
347 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
348 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::~reduction()
358 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
359 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::flush()
362 if( Internal::distributor::active() ) {
363 if( trace_level() > 0 ) {
364 Internal::Speaker oss(std::cout);
365 oss << this->name() <<
" flush: bcast ALLDONE";
370 (*ser) & DISTRED::ALLDONE;
372 m_nDones += bcast( ser, 0 );
374 try_send_or_put_all();
377 for(
typename tls_map_type::iterator i = m_reductions.begin(); i != m_reductions.end(); ++i ) {
378 m_out.put( i->first, i->second.val.combine( m_op ) );
382 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
383 typename reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::tls_map_type::iterator
384 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::get(
const OTag & tag )
386 typename tls_map_type::iterator i = m_reductions.find( tag );
387 if( i == m_reductions.end() ) {
388 i = m_reductions.insert(
typename tls_map_type::value_type( tag, red_tls() ) ).first;
395 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
396 bool reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::try_put_value(
const OTag & otag,
const typename tls_map_type::iterator & i )
398 if( trace_level() > 2 ) {
399 Internal::Speaker oss(std::cout);
400 oss << this->name() <<
" try_put_value [";
401 cnc_format( oss, otag ) <<
"]" 403 <<
" nValues " << i->second.nValues <<
" status " << i->second.status
407 if( i->second.nreduced == i->second.n ) {
409 mutex_type::scoped_lock _lock( i->second.mtx );
410 if( i->second.status != DONE ) {
411 this->m_out.put( otag, i->second.val.combine( this->m_op ) );
412 i->second.status = DONE;
422 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
423 bool reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::send_count(
const OTag & otag,
const typename tls_map_type::iterator & i,
424 const int to,
const bool always )
429 CType _cnt = i->second.nreduced.fetch_and_store( 0 );
430 if( always || _cnt > 0 ) {
432 (*ser) & DISTRED::GATHERCOUNT & otag & _cnt;
433 if( trace_level() > 2 ) {
434 Internal::Speaker oss(std::cout);
435 oss << this->name() <<
" send GATHERCOUNT [";
436 cnc_format( oss, otag ) <<
"] " << _cnt <<
" to " << to;
438 this->send_msg( ser, to );
446 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
447 int reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::my_parent_for_root(
const int root )
451 CNC_ASSERT( root != mpid );
452 int _p = ( ( ( mpid >= root ? ( mpid - root ) : ( mpid + nps - root ) ) - 1 ) / 2 ) + root;
458 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
459 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::try_send_or_put_value(
const OTag & otag,
const typename tls_map_type::iterator & i )
461 if( trace_level() > 2 ) {
462 Internal::Speaker oss(std::cout);
463 oss << this->name() <<
" try_send_or_put_value [";
464 cnc_format( oss, otag ) <<
"] nValues " << i->second.nValues <<
" status " << i->second.status;
466 if( i->second.nValues.fetch_and_decrement() == 1 ) {
468 if( i->second.status == FINISH ) {
469 CNC_ASSERT( i->second.nreduced == i->second.n || i->second.n == M1 );
470 CNC_ASSERT( i->second.nValues == 0 && i->second.status == FINISH );
471 i->second.nreduced = i->second.n;
472 try_put_value( otag, i );
476 IType _val( i->second.val.combine( this->m_op ) );
477 (*ser) & DISTRED::VALUE & otag & _val;
478 const int to = my_parent_for_root( i->second.owner );
479 if( trace_level() > 2 ) {
480 Internal::Speaker oss(std::cout);
481 oss << this->name() <<
" send VALUE [";
482 cnc_format( oss, otag ) <<
"] ";
483 cnc_format( oss, _val ) <<
" to " << to;
485 this->send_msg( ser, to );
486 i->second.status = DONE;
493 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
494 int reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::bcast(
CnC::serializer * ser,
int root )
498 int _r1 = ( ( mpid >= root ? ( mpid - root ) : ( mpid + nps - root ) ) + 1 ) * 2 - 1;
502 _r1 = (root + _r1) % nps;
503 int _recvrs[2] = { _r1, (_r1+1)%nps };
504 this->bcast_msg( ser, _recvrs, 2 );
508 _r1 = (root + _r1) % nps;
509 this->send_msg( ser, _r1 );
523 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
524 int reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::bcast_count(
const OTag & tag,
const CType & val,
const int root )
527 (*ser) & ( val != M1 ? DISTRED::BCASTCOUNT : DISTRED::DONE ) & tag & root;
528 if( val != M1 ) (*ser) & val;
529 int _c = bcast( ser, root );
530 if( _c && trace_level() > 2 ) {
531 Internal::Speaker oss(std::cout);
532 oss << this->name() <<
" bcast " << (val != M1 ?
" BCASTCOUNT [" :
" DONE [");
533 cnc_format( oss, tag ) <<
"]";
540 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
541 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::try_send_or_put_all()
543 CNC_ASSERT( m_alldone );
544 if( trace_level() > 2 ) {
545 Internal::Speaker oss(std::cout);
546 oss << this->name() <<
" try_send_or_put_all " << m_nDones;
548 if( --m_nDones == 0 ) {
550 for(
typename tls_map_type::iterator i = m_reductions.begin(); i != m_reductions.end(); ++i ) {
551 m_out.put( i->first, i->second.val.combine( m_op ) );
554 int _n = m_reductions.size();
556 (*ser) & DISTRED::ALLVALUES & _n;
557 for(
typename tls_map_type::iterator i = m_reductions.begin(); i != m_reductions.end(); ++i ) {
558 IType _val( i->second.val.combine( this->m_op ) );
559 (*ser) & i->first & _val;
561 const int to = my_parent_for_root( 0 );
562 if( trace_level() > 2 ) {
563 Internal::Speaker oss(std::cout);
564 oss << this->name() <<
" send ALLVALUES to " << to;
566 this->send_msg( ser, to );
573 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
574 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::recv_msg(
serializer * ser )
580 case DISTRED::GATHERCOUNT : {
583 (*ser) & _tag & _cnt;
584 if( trace_level() > 2 ) {
585 Internal::Speaker oss(std::cout);
586 oss << this->name() <<
" recvd GATHERCOUNT [";
587 cnc_format( oss, _tag ) <<
"] " << _cnt;
589 m_oncount->on_gatherCount( _tag,
get( _tag ), _cnt );
592 case DISTRED::BCASTCOUNT : {
596 (*ser) & _tag & _owner & _cnt ;
597 if( trace_level() > 2 ) {
598 Internal::Speaker oss(std::cout);
599 oss << this->name() <<
" recvd BCASTCOUNT [";
600 cnc_format( oss, _tag ) <<
"] " << _cnt <<
" " << _owner;
602 m_oncount->on_bcastCount( _tag,
get( _tag ), _cnt, _owner );
605 case DISTRED::VALUE : {
608 (*ser) & _tag & _val;
609 if( trace_level() > 2 ) {
610 Internal::Speaker oss(std::cout);
611 oss << this->name() <<
" recvd VALUE [";
612 cnc_format( oss, _tag ) <<
"] ";
613 cnc_format( oss, _val );
615 m_ondata->on_value( _tag,
get( _tag ), _val );
618 case DISTRED::DONE : {
621 (*ser) & _tag & _owner;
622 if( trace_level() > 2 ) {
623 Internal::Speaker oss(std::cout);
624 oss << this->name() <<
" recvd DONE [";
625 cnc_format( oss, _tag ) <<
"] " << _owner;
627 m_oncount->on_done( _tag,
get( _tag ), _owner );
630 case DISTRED::ALLDONE : {
631 if( trace_level() > 2 ) {
632 Internal::Speaker oss(std::cout);
633 oss << this->name() <<
" recvd ALLDONE";
637 (*ser) & DISTRED::ALLDONE;
639 m_nDones += bcast( ser, 0 );
641 try_send_or_put_all();
645 case DISTRED::ALLVALUES : {
646 CNC_ASSERT( m_alldone =
true );
649 if( trace_level() > 2 ) {
650 Internal::Speaker oss(std::cout);
651 oss << this->name() <<
" recvd ALLVALUES " << _n;
656 (*ser) & _tag & _val;
657 const typename tls_map_type::iterator i =
get( _tag );
658 m_ondata->add_value( i, _val );
660 try_send_or_put_all();
663 CNC_ASSERT_MSG(
false,
"Unexpected message tag in JOIN" );
672 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
673 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_item_put::on_item_put( reduce_type * r )
679 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
680 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_item_put::add_value(
const typename tls_map_type::iterator & i,
const IType & val )
const 683 IType & _rval = i->second.val.local( _exists );
684 _rval = m_reduce->m_op( _exists ? _rval : m_reduce->m_identity, val );
690 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
691 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_item_put::on_value(
const OTag & otag,
const typename tls_map_type::iterator & i,
const IType & val )
693 TRACE(
"::on_value" );
695 m_reduce->try_send_or_put_value( otag, i );
701 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
702 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_item_put::on_put(
const ITag & tag,
const IType & val )
704 TRACE(
"::on_data" );
706 if( m_reduce->m_sel( tag, otag ) ) {
707 typename tls_map_type::iterator i = m_reduce->get( otag );
709 CType _n = ++i->second.nreduced;
710 if( m_reduce->trace_level() > 0 ) {
711 Internal::Speaker oss(std::cout);
712 oss << m_reduce->name() <<
" on_put [";
713 cnc_format( oss, tag ) <<
"] for [";
714 cnc_format( oss, otag ) <<
"] ";
715 cnc_format( oss, val );
716 oss <<
" nred now " << _n <<
"/" << i->second.n
718 <<
" owner " << i->second.owner <<
" status " << i->second.status <<
" nCounts " << i->second.nCounts
724 if( Internal::distributor::active() ) {
729 if( i->second.status >= CNT_AVAILABLE ) {
732 if( _n == i->second.n && i->second.nCounts <= 0 ) m_reduce->m_oncount->on_done( otag, i,
CnC::tuner_base::myPid() );
739 m_reduce->send_count( otag, i, i->second.owner,
false );
745 m_reduce->try_put_value( otag, i );
746 }
else if( m_reduce->trace_level() > 0 ) {
747 Internal::Speaker oss(std::cout);
748 oss << m_reduce->name() <<
" [";
749 cnc_format( oss, tag ) <<
"] was not selected";
756 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
757 reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_count_put::on_count_put( reduce_type * r )
764 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
765 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_count_put::on_done(
const OTag & otag,
const typename tls_map_type::iterator & i,
const int owner )
767 TRACE(
"::on_done" );
768 if( m_reduce->trace_level() > 2 ) {
769 Internal::Speaker oss(std::cout);
770 oss << m_reduce->name() <<
" on_done for [";
771 cnc_format( oss, otag ) <<
"] nred now " << i->second.nreduced <<
"/" << i->second.n
772 <<
" owner " << i->second.owner <<
" status " << i->second.status;
774 i->second.owner = owner;
775 if( owner !=
CnC::tuner_base::myPid() || i->second.status.compare_and_swap( BCAST_DONE, CNT_AVAILABLE ) == CNT_AVAILABLE ) {
777 i->second.nValues = 1000;
778 i->second.nValues += m_reduce->bcast_count( otag, M1, owner );
779 int _tmp = i->second.status.compare_and_swap( FINISH, BCAST_DONE );
782 i->second.nValues -= 999;
784 m_reduce->try_send_or_put_value( otag, i );
790 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
791 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_count_put::on_bcastCount(
const OTag & otag,
const typename tls_map_type::iterator & i,
const CType & cnt,
const int owner )
793 TRACE(
"::on_bcast" );
794 CNC_ASSERT( cnt != M1 );
795 i->second.owner = owner;
798 int _tmp = i->second.status.compare_and_swap( CNT_AVAILABLE, LOCAL );
799 CNC_ASSERT( _tmp == LOCAL );
801 i->second.nCounts = 1;
802 i->second.nCounts += m_reduce->bcast_count( otag, cnt, owner );
805 m_reduce->send_count( otag, i, my_parent_for_root( owner ),
true );
811 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
812 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_count_put::on_gatherCount(
const OTag & otag,
const typename tls_map_type::iterator & i,
const CType & cnt )
814 TRACE(
"::on_gather" );
815 CNC_ASSERT( cnt != M1 );
816 i->second.nreduced += cnt;
817 if( m_reduce->trace_level() > 2 ) {
818 Internal::Speaker oss(std::cout);
819 oss << m_reduce->name() <<
" on_gatherCount [";
820 cnc_format( oss, otag ) <<
"] now " << i->second.nreduced <<
"/" << i->second.n <<
" nCounts " << i->second.nCounts;
823 if( --i->second.nCounts <= 0 ) {
825 if( i->second.n == i->second.nreduced ) {
829 CNC_ASSERT( i->second.nCounts == 0 );
830 m_reduce->send_count( otag, i, my_parent_for_root( i->second.owner ),
true );
838 template<
typename ITag,
typename IType,
typename ITuner,
typename CType,
typename CTuner,
typename OTag,
typename OTuner,
typename ReduceOp,
typename Select >
839 void reduction< ITag, IType, ITuner, CType, CTuner, OTag, OTuner, ReduceOp, Select >::on_count_put::on_put(
const OTag & otag,
const CType & cnt )
842 typename tls_map_type::iterator i = m_reduce->get( otag );
845 if( Internal::distributor::active() ) {
849 if( ! m_reduce->try_put_value( otag, i ) ) {
855 int _tmp = i->second.status.compare_and_swap( CNT_AVAILABLE, LOCAL );
856 CNC_ASSERT( _tmp == LOCAL );
857 i->second.nCounts = 0;
863 if( cnt != M1 ) i->second.n = cnt;
864 else i->second.n = i->second.nreduced;
865 m_reduce->try_put_value( otag, i );
875 #endif //_CnC_REDUCE_H_
Base class for defining and using CnC (sub-)graphs.
CnC context bringing together collections (for steps, items and tags).
graph * make_reduce_graph(CnC::context< Ctxt > &ctxt, const std::string &name, CnC::item_collection< ITag, IType, ITuner > &in, CnC::item_collection< OTag, CType, CTuner > &cnt, CnC::item_collection< OTag, IType, OTuner > &out, const ReduceOp &op, const IType &idty, const Select &sel)
Handles serilialization of data-objects.
An item collection is a mapping from tags to items.