CnC
default_tuner.h
1 /* *******************************************************************************
2  * Copyright (c) 2007-2014, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * * Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of Intel Corporation nor the names of its contributors
13  * may be used to endorse or promote products derived from this software
14  * without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  ********************************************************************************/
27 
28 /*
29  CnC tuner interface(s).
30 */
31 
32 #ifndef CNC_DEFAULT_TUNER_H_ALREADY_INCLUDED
33 #define CNC_DEFAULT_TUNER_H_ALREADY_INCLUDED
34 
35 #include <cnc/internal/cnc_api.h>
36 #include <cnc/default_partitioner.h>
37 #include <cnc/internal/step_delayer.h>
38 #include <cnc/internal/cnc_tag_hash_compare.h>
39 #include <cnc/internal/no_range.h>
40 #include <cnc/internal/no_tag_table.h>
41 #include <cnc/internal/hash_tag_table.h>
42 #include <cnc/internal/item_properties.h>
43 #include <cnc/internal/item_properties.h>
44 #include <cnc/internal/dist/distributor.h>
45 #include <cnc/internal/tbbcompat.h>
46 #include <tbb/atomic.h>
47 #include <tbb/concurrent_unordered_set.h>
48 //#include <tbb/concurrent_hash_map.h>
49 
50 namespace CnC {
51 
52  template< class T > class context;
53  namespace Internal {
54  template< class Tag, class Range, class StepColl, class RangeStepI, class TIR, bool deps > struct range_step;
55  }
56 
57  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
58  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 
60  // Key-words tuning
61  enum {
62  COMPUTE_ON_LOCAL = -2, ///< let tuner::compute_on return COMPUTE_ON_LOCAL if the step should be executed locally
63  COMPUTE_ON_ROUND_ROBIN = -3, ///< let tuner::compute_on return COMPUTE_ON_ROUND_ROBIN to let the scheduler distribute it in a round-robin fashion
64  COMPUTE_ON_ALL = -4, ///< let tuner::compute_on return COMPUTE_ON_ALL if the step should be executed on all processes, as well as locally
65  COMPUTE_ON_ALL_OTHERS = -5, ///< let tuner::compute_on return COMPUTE_ON_ALL_OTHERS if the step should be executed on all processes, but not locally
66  PRODUCER_UNKNOWN = -6, ///< producer process of dependent item is unknown
67  PRODUCER_LOCAL = -7, ///< producer process of dependent item is local process
68  CONSUMER_UNKNOWN = -8, ///< consumer process of given item is unkown
69  CONSUMER_LOCAL = -9, ///< consumer process of given item is the local process
70  CONSUMER_ALL = -10, ///< all processes consume given item
71  CONSUMER_ALL_OTHERS = -11, ///< all processes but this consume given item
72  NO_GETCOUNT = Internal::item_properties::NO_GET_COUNT, ///< no get-count specified
73  AFFINITY_HERE = Internal::scheduler_i::AFFINITY_HERE ///< default affinity to current thread
74  };
75 
76  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
78 
79  /// Functionality that might be needed to implement all kinds of tuners.
80  /// Always try to use higher level tuners which derive from this.
81  /// Always use virtual inheritance (see higher level tuners).
82  class tuner_base
83  {
84  public:
85  /// returns id/rank of calling process
86  /// defaults to 0 if running on one process only.
87  inline static int myPid()
88  {
89  return Internal::distributor::myPid();
90  }
91  /// return total number of processes participating in this programm execution
92  /// defaults to 1 if running on one process only.
93  inline static int numProcs()
94  {
95  return Internal::distributor::numProcs();
96  }
97  /// returns number of threads used by scheduler in given context
98  template< typename Ctxt >
99  inline static int numThreads( const Ctxt & ctxt )
100  {
101  return ctxt.numThreads();
102  }
103  };
104 
105 
106  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
107  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108 
109  /// \brief Default (NOP) implementations of the step_tuner interface.
110  ///
111  /// Also defines the interface a user-provided tuner must satisfy.
112  /// Derive your tuner from this (to avoid implementing the entire interface).
113  ///
114  /// It is recommended that your tuner does not implement the methods as templates.
115  /// Instead, you should use the actual types that it expects.
116  ///
117  /// \#include <cnc/default_tuner.h>
118  template< bool check_deps = true >
119  struct /*CNC_API*/ step_tuner : public virtual tuner_base
120  {
121  /// \brief Allows definition of priorities to individual steps (which are identified by the tag).
122  /// \return the default implementation always return 1.
123  /// \param tag the tag which identifies the step to be executed
124  /// \param arg the argument as passed to context< Derived >::prescribed (usually the context)
125  /// \see also CNCROOT/samples/floyd_warshall
126  template< typename Tag, typename Arg >
127  int priority( const Tag & tag, Arg & arg ) const
128  {
129  return 1;
130  }
131 
132  /// \brief Allows declaration of data dependencies (to items) of
133  /// given step (identified by the tag).
134  ///
135  /// When a step-instance is prescribed through a corresponding
136  /// tag_collection::put, this method will be called. You can
137  /// declare dependencies to items by calling
138  /// dC.depends( item_collection, dependent_item_tag )
139  /// for every item the step is going to 'get' in its execute
140  /// method. The actual step execution will be delayed until
141  /// all dependencies can be satisfied. The default
142  /// implementation does nothing (NOP). Your implementation
143  /// must accept dC by reference (T&).
144  /// \param tag the tag which identifies the step to be executed.
145  /// \param arg the argument as passed to context< Derived >::prescribed
146  /// (usually the context)
147  /// \param dC opaque object (must be by reference!) providing method depends
148  /// to declare item dependencies
149  template< typename Tag, typename Arg, typename T >
150  void depends( const Tag & tag, Arg & arg, T & dC ) const
151  {
152  }
153 
154  /// \brief Returns whether the step should be pre-scheduled
155  ///
156  /// Pre-scheduling provides an alternative method for detecting
157  /// data dependencies, in particular if it is combined with
158  /// item_collection::unsafe_get and context::flush_gets() in the
159  /// step-code.
160  ///
161  /// The step instance will be run immediately when prescribed
162  /// by a tag_collection::put. All items that are not yet
163  /// available when accessed by the blocking
164  /// item_collection::get() and/or non-blocking
165  /// item_collection::unsafe_get() methods will automatically
166  /// be treated as dependent items. The pre-run will end at the
167  /// first unsuccessful blocking get or at
168  /// context::flush_gets() (if any items got through
169  /// item_collection::unsafe_get() were unavailable). Execution
170  /// stops by throwing an exception, similar to un unsuccessful
171  /// item_collection::get(). The step execution will be delayed
172  /// until all detected dependencies can be satisfied.
173  /// \note If all dependent items are available in the pre-scheduling
174  /// execution the step gets fully executed. This can lead to
175  /// very deep call-stacks if items are always available and
176  /// new control is produced in steps.
177  bool preschedule() const
178  {
179  return false;
180  }
181 
182  /// \brief Tell the scheduler the preferred thread for executing given step
183  ///
184  /// Not all schedulers might actually evaluate this call (see \ref scheduler);
185  /// it involves a virtual function call whenever a step is (re-)scheduled.
186  /// This feature is most useful in combination with
187  /// the CNC_PIN_THREADS environment variable (\ref priorpin).
188  /// \return thread id or AFFINITY_HERE (default)
189  template< typename Tag, typename Arg >
190  int affinity( const Tag & /*tag*/, Arg & /*arg*/ ) const
191  {
192  return AFFINITY_HERE;
193  }
194 
195  /// \brief tell the scheduler on which process to run the step
196  /// (or range of steps) (distCnC)
197  ///
198  /// return process id where the step will be executed, or
199  /// COMPUTE_ON_ROUND_ROBIN, or COMPUTE_ON_LOCAL, or
200  /// COMPUTE_ON_ALL, or COMPUTE_ON_ALL_OTHERS
201  template< typename Tag, typename Arg >
202  int compute_on( const Tag & /*tag*/, Arg & /*arg*/ ) const
203  {
204  return COMPUTE_ON_ROUND_ROBIN;
205  }
206 
207  /// \brief true if steps launched through ranges consume items
208  /// or need global locking, false otherwise.
209  ///
210  /// Avoiding checks for dependencies and global locks saves
211  /// overhead and will perform better (e.g. for parallel_for).
212  /// Safe execution (with checks) is the default (check_deps
213  /// template argument).
214  static const bool check_deps_in_ranges = check_deps;
215 
216  /// \brief check for cancelation of given step
217  ///
218  /// \return true if step was canceled, false otherwise (default)
219  /// \note Must be thread-safe.
220  /// Runtime will try to not execute the step, but it might still get executed.
221  /// Best effort - but no guarantees.
222  /// Canceling steps makes all determinism guarantees void.
223  ///
224  /// For distributed memory your implementation might require to sync its state
225  /// across processes. Currently there is no API exposed to do that conveniently.
226  /// However, an example implementatino CnC::cancel_tuner is provided which
227  /// works on distributed memory.
228  /// \see also CNCROOT/samples/floyd_warshall
229  template< typename Tag, typename Arg >
230  int was_canceled( const Tag & /*tag*/, Arg & /*arg*/ ) const
231  {
232  return false;
233  }
234 
235  /// \brief check if given step-instance needs to be executed sequentially
236  /// \return false by default, if true, step-instance gets queued for execution
237  /// in a sequential phase (after all workers are quienscent)
238  template< typename Tag, typename Arg >
239  bool sequentialize( const Tag & /*tag*/, Arg & /*arg*/ ) const
240  {
241  return false;
242  }
243  };
244 
245  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 
247  /// \brief Default (NOP) implementations of the pfor_tuner interface.
248  ///
249  /// Also defines the interface a user-provided step-tuner must satisfy.
250  /// Derive your tuner from this (to avoid implementing the entire interface).
251  ///
252  /// It is recommended that your tuner does not implement the methods as templates.
253  /// Instead, you should use the actual types that it expects.
254  ///
255  /// \#include <cnc/default_tuner.h>
256  template< bool check_deps = true, typename Partitioner = default_partitioner<> >
257  struct /*CNC_API*/ pfor_tuner : public virtual tuner_base
258  {
259  template< typename Tag, typename Arg >
260  int priority( const Tag & tag, Arg & arg ) const
261  {
262  return 1;
263  }
264 
265  template< typename Tag, typename Arg, typename T >
266  void depends( const Tag & tag, Arg & arg, T & dC ) const
267  {
268  }
269 
270  bool preschedule() const
271  {
272  return false;
273  }
274 
275  template< typename Tag, typename Arg >
276  int affinity( const Tag & /*tag*/, Arg & /*arg*/ ) const
277  {
278  return AFFINITY_HERE;
279  }
280 
281  static const bool check_deps_in_ranges = check_deps;
282 
283  typedef Partitioner partitioner_type;
284 
285  partitioner_type partitioner() const
286  {
287  return typename pfor_tuner< check_deps, Partitioner >::partitioner_type();
288  }
289  };
290 
291  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
292  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
293 
294  namespace CT {
295 #ifdef _DIST_CNC_
296  static const char SINGLE = 0; // single tag
297  static const char ALL = 1; // cancel all
298  static const char RESET = 2; // reset
299 #endif
300  }
301 
302  /// \brief Step tuner with convenient cancelation capabilities
303  ///
304  /// Allows cancelation of individual step-instances by their tags as well as
305  /// canceling all instances at once. All cancelation requests are "active" until
306  /// unsafe_reset() is called (or the tuner is destructed).
307  ///
308  /// To use it, you need a cancel_tuner object in your context which you pass
309  /// to the constructor of the respective step_collection.
310  ///
311  /// It works on distributed memory but might perform poorly if used frequently.
312  ///
313  /// \param Tag tag-type
314  /// \param check_deps if false, avoid some mechanics to handle unavailable items
315  /// \param Hasher hash-functor for Tag, defaults to tbb::tbb_hash< Tag >
316  /// \param Equality equality operator for Tag, defaults to std::equal_to< Tag >
317  /// \note It is assumed that cancelation per instance happens relatively rarely. Hence
318  /// no automatic garbage collection of the tags is provided. If you cancel individual
319  /// step-instances frequently, it is recommended to prune the internal data structure
320  /// from time to time in a safe state through unsafe_reset().
321  /// \see also CNCROOT/samples/floyd_warshall
322  template< typename Tag, bool check_deps = true,
323  typename Hasher = cnc_hash< Tag >, typename Equality = cnc_equal< Tag > >
324  class cancel_tuner : public step_tuner< check_deps >, public Internal::distributable
325  {
326  public:
327  template< typename C >
328  cancel_tuner( C & ctxt )
329  : Internal::distributable( "cancel_tuner" ), m_context( ctxt ), m_canceledTags(), m_cancelAll()
330  {
331  m_context.subscribe( this );
332  m_cancelAll = false;
333  }
334 
335  ~cancel_tuner()
336  {
337  m_context.unsubscribe( this );
338  }
339 
340  /// \brief cancel given step (identified by tag)
341  void cancel( const Tag & t, bool from_msg = false )
342  {
343  if( ! m_cancelAll ) {
344 #ifdef _DIST_CNC_
345  if( !from_msg && Internal::distributor::numProcs() > 1 ) {
346  serializer * _ser = m_context.new_serializer( this );
347  (*_ser) & CT::SINGLE & t;
348  m_context.bcast_msg( _ser );
349  }
350 #endif
351  m_canceledTags.insert( t );
352  }
353  }
354 
355  /// \brief cancel all steps
356  void cancel_all( bool from_msg = false )
357  {
358 #ifdef _DIST_CNC_
359  if( !from_msg && Internal::distributor::numProcs() > 1 ) {
360  serializer * _ser = m_context.new_serializer( this );
361  (*_ser) & CT::ALL;
362  m_context.bcast_msg( _ser );
363  }
364 #endif
365  m_cancelAll = true;
366  }
367 
368  void unsafe_reset( )
369  {
370  unsafe_reset( true );
371  }
372 
373  /// \brief implements/overwrites step_tuner::was_canceled(...)
374  template< typename Arg >
375  int was_canceled( const Tag & tag, Arg & /*arg*/ ) const
376  {
377  return m_cancelAll == true || m_canceledTags.count( tag ) > 0;
378  }
379 
380  // from distributable
381  virtual void recv_msg( serializer * ser )
382  {
383 #ifdef _DIST_CNC_
384  CNC_ASSERT( Internal::distributor::active() );
385  char _msg;
386  (*ser) & _msg;
387  switch( _msg ) {
388  case CT::SINGLE :
389  Tag _tag;
390  (*ser) & _tag;
391  this->cancel( _tag, true );
392  break;
393  case CT::ALL :
394  this->cancel_all( true );
395  break;
396  case CT::RESET :
397  this->unsafe_reset( false );
398  break;
399  default:
400  CNC_ABORT( "Unexpected message received (cancel_tuner)." );
401  }
402 #endif
403  }
404 
405  private:
406  /// \brief reset all current cancel states
407  /// \note not thread-safe, to be called in safe state only
408  /// (between program start or calling context::wait() and putting the first tag or item).
409  virtual void unsafe_reset( bool dist )
410  {
411 #ifdef _DIST_CNC_
412  if( dist && Internal::distributor::numProcs() > 1 ) {
413  serializer * _ser = m_context.new_serializer( this );
414  (*_ser) & CT::RESET;
415  m_context.bcast_msg( _ser );
416  }
417 #endif
418  m_canceledTags.clear();
419  m_cancelAll = false;
420  }
421 
422  Internal::distributable_context & m_context;
423  tbb::concurrent_unordered_set< Tag, Hasher, Equality > m_canceledTags;
424  tbb::atomic< bool > m_cancelAll;
425  };
426 
427 
428  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
429  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 
431  /// \brief Default implementations of the item-tuner interface for item-collections
432  ///
433  /// Usually you will not need to use this directly for anything else than documentation and interface.
434  template< template< typename T, typename I, typename A > class TT >
435  struct item_tuner : public virtual tuner_base
436  {
437  /// \brief Class which manages item creation/uncreation..
438  ///
439  /// item_allocator::type must provide
440  /// item_type * create( const item_type & org ) const;
441  /// void uncreate( item_type * item ) const;
442  ///
443  /// Only C++0x allows template aliasing, need to use an indirection
444  template< typename Item >
446  {
447  // typedef CnC::Internal::item_manager_default< Item > type;
448  typedef tbb::scalable_allocator< Item > type;
449  };
450 
451  /// \brief Defines the type of the internal data store.
452  ///
453  /// It forwards the functionality of the template parameter template.
454  /// The expected interface of the template is not yet exposed.
455  /// Use hashmap_tuner or vector_tuner to derive your own tuner.
456  template< typename Tag, typename Item, typename Coll >
457  struct table_type : public TT< Tag, Item, Coll >
458  {
459  table_type( const Coll * c, size_t sz = 0 ) : TT< Tag, Item, Coll >( c, sz ) {}
460  };
461 
462  /// \brief Initialize the internal storage.
463  ///
464  /// Can be used to configure the storage table.
465  /// Called in the collection constructor.
466  template< typename Tag, typename Item, typename Coll >
467  void init_table( TT< Tag, Item, Coll > & stbl ) const
468  {}
469 
470  /// \brief Allows specifying the number of gets to the given item.
471  ///
472  /// After get_count() many 'get()'s the item can be removed from the collection.
473  /// By default, the item is not removed until the collection is deleted.
474  /// Gets by the environment are ignored, use CnC::NO_GETCOUNT for items
475  /// which are consumed by the environment.
476  /// \param tag the tag which identifies the item
477  /// \return number of expected gets to this item, or CNC::NO_GETCOUNT
478  template< typename Tag >
479  int get_count( const Tag & tag ) const
480  {
481  return NO_GETCOUNT;
482  }
483 
484  /// \brief Tells the scheduler on which process(es) this item is going to be consumed
485  ///
486  /// return process id where the item will be consumed (get), or CONSUMER_UNKNOWN (default)
487  /// or std::vector<int>, containing all ids of consuming processes.
488  /// To indicate that the consumer processes are unknown, return an empty vector.
489  /// The vector must contain special values like CONSUMER_LOCAL.
490  /// If not CnC::CONSUMER_UKNOWN (or empty vector), this declaration will overwrite what
491  /// the step-tuner might declare in depends.
492  /// Providing this method leads to the most efficient communication pattern for
493  /// to getting the data to where it is needed.
494  /// \param tag the tag which identifies the item
495  template< typename Tag >
496  int consumed_on( const Tag & tag ) const
497  {
498  return CONSUMER_UNKNOWN;
499  }
500 
501  /// \brief Tells the scheduler on which process(es) this item is going to be produced
502  ///
503  /// return process id where the item will be produced. If unknown return CnC::PRODUCER_UNKNOWN.
504  /// return PRODUCER_LOCAL if local process is the owner.
505  /// Implementing this method reduces the communication cost for locating and sending data.
506  /// Implementing item_tuner::consumed_on is more efficient, but might be more complicated.
507  /// Will be evaluated only if item_tuner::consumed_on returns CnC::CONSUMER_UNKNOWN
508  /// \param tag the tag which identifies the item
509  template< typename Tag >
510  int produced_on( const Tag & tag ) const
511  {
512  return PRODUCER_UNKNOWN;
513  }
514  };
515 
516  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
517 
518  namespace Internal {
519  template< typename Tag, typename ItemT, typename Coll > class hash_item_table;
520  template< typename Tag, typename ItemT, typename Coll > class vec_item_table;
521  }
522 
523  /// \brief The tuner base for hashmap-based item-tuners.
524  ///
525  /// The internal hash-map uses cnc_tag_hash_compare. If your
526  /// tag-type is not supported by default, you need to provide a
527  /// template specialization for it.
528  struct hashmap_tuner : public item_tuner< Internal::hash_item_table >
529  {
530  };
531 
532  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
533 
534  /// \brief The tuner base for vector-based item-tuners.
535  ///
536  /// Your tags must be convertable to and from size_t. You must
537  /// provide the maximum value before accessing the collection
538  /// (constructor or set_max). The runtime will allocate as many
539  /// slots. Hence, use this only if your tags-space is dense,
540  /// without a large offset and if it is not too large.
541  struct vector_tuner : public item_tuner< Internal::vec_item_table >
542  {
543  };
544 
545  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
546  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
547 
548  /// \brief Default implementations of the tag-tuner interface for tag-collections
549  ///
550  /// Use this if you are going put ranges. Optional argument is a custom partitioner.
551  /// Ranges don't work with memoization (yet)
552  template< typename Range = Internal::no_range, typename Partitioner = default_partitioner<> >
553  struct tag_tuner : public virtual tuner_base
554  {
555  /// A tag tuner must provide the type of the range, default is no range
556  typedef Range range_type;
557  /// A tag tuner must provide a tag-table type; default is no tag-table
558  typedef Internal::no_tag_table tag_table_type;
559  /// \brief The type of the partitioner
560  typedef Partitioner partitioner_type;
561 
562  /// \brief return a partitioner for range-based features, such as parallel_for
563  /// \see default_partitioner for the expected signature of partitioners
564  /// overwrite partitioner() if it doesn't come with default-constructor or
565  /// if the default constructor is insufficient.
566  partitioner_type partitioner() const
567  {
569  }
570 
571  /// return true if tag memoization is wanted; returns false by default (with no_tag_table)
572  bool preserve_tags() const
573  {
574  return false;
575  };
576  };
577 
578  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
579 
580  /// Use this if your tag-collection should preserve tags (memoization)
581  /// \note Memoization doesn't work with ranges (yet)
582  template< typename Tag, typename H = cnc_hash< Tag >, typename E = cnc_equal< Tag > >
583  struct preserve_tuner : public tag_tuner< Internal::no_range, default_partitioner<> >
584  {
585  /// A tag tuner must provide a tag-table type; default is no tag-table
586  typedef Internal::hash_tag_table< Tag, H, E > tag_table_type;
587 
588  bool preserve_tags() const
589  {
590  return true;
591  };
592  };
593 
594  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
595  // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
596 
597  namespace Internal {
598  template< typename Tuner >
599  const Tuner & get_default_tuner()
600  {
601  static tbb::atomic< Tuner * > s_tuner;
602  if( s_tuner == NULL ) {
603  Tuner * _tmp = new Tuner;
604  if( s_tuner.compare_and_swap( _tmp, NULL ) != NULL ) delete _tmp;
605  }
606  return *s_tuner;
607  }
608  }
609 
610 } // end namespace CnC
611 
612 #endif //CNC_DEFAULT_TUNER_H_ALREADY_INCLUDED
int priority(const Tag &tag, Arg &arg) const
Allows definition of priorities to individual steps (which are identified by the tag).
The tuner base for vector-based item-tuners.
int was_canceled(const Tag &tag, Arg &) const
implements/overwrites step_tuner::was_canceled(...)
Provides hash operators for hashing.
default affinity to current thread
Definition: default_tuner.h:73
Partitioner partitioner_type
The type of the partitioner.
let tuner::compute_on return COMPUTE_ON_ALL_OTHERS if the step should be executed on all processes...
Definition: default_tuner.h:65
no get-count specified
Definition: default_tuner.h:72
Default (NOP) implementations of the pfor_tuner interface.
void cancel(const Tag &t, bool from_msg=false)
cancel given step (identified by tag)
all processes consume given item
Definition: default_tuner.h:70
consumer process of given item is unkown
Definition: default_tuner.h:68
int compute_on(const Tag &, Arg &) const
tell the scheduler on which process to run the step (or range of steps) (distCnC) ...
CnC API.
Definition: cnc.h:49
static int numThreads(const Ctxt &ctxt)
returns number of threads used by scheduler in given context
Definition: default_tuner.h:99
int consumed_on(const Tag &tag) const
Tells the scheduler on which process(es) this item is going to be consumed.
Default implementations of the item-tuner interface for item-collections.
void init_table(TT< Tag, Item, Coll > &stbl) const
Initialize the internal storage.
partitioner_type partitioner() const
return a partitioner for range-based features, such as parallel_for
Default (NOP) implementations of the step_tuner interface.
Range range_type
A tag tuner must provide the type of the range, default is no range.
Internal::no_tag_table tag_table_type
A tag tuner must provide a tag-table type; default is no tag-table.
consumer process of given item is the local process
Definition: default_tuner.h:69
Default implementations of the tag-tuner interface for tag-collections.
int get_count(const Tag &tag) const
Allows specifying the number of gets to the given item.
The tuner base for hashmap-based item-tuners.
producer process of dependent item is unknown
Definition: default_tuner.h:66
Defines the type of the internal data store.
producer process of dependent item is local process
Definition: default_tuner.h:67
Step tuner with convenient cancelation capabilities.
void depends(const Tag &tag, Arg &arg, T &dC) const
Allows declaration of data dependencies (to items) of given step (identified by the tag)...
int was_canceled(const Tag &, Arg &) const
check for cancelation of given step
static int numProcs()
Definition: default_tuner.h:93
Handles serilialization of data-objects.
Definition: serializer.h:348
Provides equality operators for hashing.
let tuner::compute_on return COMPUTE_ON_LOCAL if the step should be executed locally ...
Definition: default_tuner.h:62
Internal::hash_tag_table< Tag, H, E > tag_table_type
A tag tuner must provide a tag-table type; default is no tag-table.
Class which manages item creation/uncreation..
static int myPid()
Definition: default_tuner.h:87
void cancel_all(bool from_msg=false)
cancel all steps
bool sequentialize(const Tag &, Arg &) const
check if given step-instance needs to be executed sequentially
int produced_on(const Tag &tag) const
Tells the scheduler on which process(es) this item is going to be produced.
all processes but this consume given item
Definition: default_tuner.h:71
bool preserve_tags() const
return true if tag memoization is wanted; returns false by default (with no_tag_table) ...
let tuner::compute_on return COMPUTE_ON_ROUND_ROBIN to let the scheduler distribute it in a round-rob...
Definition: default_tuner.h:63
let tuner::compute_on return COMPUTE_ON_ALL if the step should be executed on all processes...
Definition: default_tuner.h:64
bool preschedule() const
Returns whether the step should be pre-scheduled.
int affinity(const Tag &, Arg &) const
Tell the scheduler the preferred thread for executing given step.