示例#1
0
  KOKKOS_INLINE_FUNCTION
  void operator()( typename policy_type::member_type & )
    {
       enum { CHUNK = 8 };
       const int n = CHUNK < m_count ? CHUNK : m_count ;

       if ( 1 < m_count ) {
         future_type f[ CHUNK ] ;

         const int inc = ( m_count + n - 1 ) / n ;

         for ( int i = 0 ; i < n ; ++i ) {
           long begin = i * inc ;
           long count = begin + inc < m_count ? inc : m_count - begin ;
           f[i] = m_policy.task_spawn( TestTaskDependence(count,m_policy,m_accum) , Kokkos::TaskSingle );
         }

         m_count = 0 ;

         m_policy.respawn( this , m_policy.when_all( n , f ) );
       }
       else if ( 1 == m_count ) {
         Kokkos::atomic_increment( & m_accum() );
       }
    }
示例#2
0
 /*!
  * \brief Access cache data
  *
  * Accessor to the data (values) stored in cache. If the specified key exists in the cache, it's usage count will be touched and reference to the element is returned.
  * The data object itself is kept in the cache, so the reference will be valid until it is removed (either manually or due to cache overflow) or cache object destroyed.
  *
  * \param <_k> key to the data
  *
  * \throw  <exception_invalid_key> Thrown when non-existent key is supplied. You could use \link cache::check check member \endlink or \link cache::count count member \endlink to check cache existence prior to fetching the data
  *
  * \return constand reference to the data, mapped by the key. of type Data of course.
  *
  * \see check
  */
 const Data& fetch(const Key& _k) {
     if (!this->_check(_k)) {
         throw exception_invalid_key("Key is not in cache",_k);
     }
     _policy->touch(_k);
     return (*(_storage.find(_k))).second;
 }
示例#3
0
 /*!
  * \brief Safe cache data access
  *
  * Accessor to the data (values) stored in cache. If the specified key exists in the cache, it's usage count will be touched
  * and reference to the element, wrapped to boost::optional  is returned.  For non-exsitent key empty boost::optional container is returned
  * The data object itself is kept in the cache, so the reference will be valid until it is removed (either manually or due to cache overflow) or cache object destroyed.
  *
  *  This function is only available if USE_BOOST_OPTIONAL macro is defined
  *
  * \param <_k> key to the data
  *
  * \return constant boost::optional wrapper, holding constant reference to the data, in case when key were in the cache,
  * or empty constant boost::optional wrapper for non-existent key.
  *
  * \see check, fetch
  */
 const boost::optional<const Data&> get(const Key& _k) throw() {
     write_lock_type l = lock.lockWrite();
     if (!this->_check(_k)) {
         return boost::optional<const Data&>();
     }
     _policy->touch(_k);
     return boost::optional<const Data&>((*(_storage.find(_k))).second);
 }
示例#4
0
        size_type _erase ( const key_type& x ) throw() {
            size_type ret=_storage.erase(x);
            _policy->remove(x);

            _currEntries-=ret;

            return ret;
        }
示例#5
0
    static KOKKOS_INLINE_FUNCTION
    future_type create(policy_type &policy, const TaskFunctorType &func) {

      future_type f ;
      // while ( f.is_null() ) {
        f = policy.task_create_team(func, _max_task_dependence);
      // }
      if ( f.is_null() ) Kokkos::abort("task_create_team FAILED, out of memory");
      return f ;
    }
示例#6
0
        /*!
         * \brief Insert element to the cache
         *
         * The cache is extended by inserting a single new element. This effectively increases the cache size. Because cache do not allow for duplicate key values, the insertion operation checks for each element inserted whether another element exists already in the container with the same key value, if so, the element is not inserted and its mapped value is not changed in any way.
         * Extension of cache could result in removal of some elements, depending of the cache fullness and used policy. It is also possible, that removal of excessive entries
         * will fail, therefore insert operation will fail too.
         *
         * \throw <exception_cache_full>  Thrown when there are no available space in the cache and policy doesn't allows removal of elements.
         * \throw <exception_invalid_key> Thrown when the policy doesn't accepts the key
         *
         * \return true if the new elemented was inserted or false if an element with the same key existed.
         */
        bool insert(Key _k, Data _d) {
            write_lock_type l = lock.lockWrite();
            while (this->_currEntries >= this->_maxEntries) {
                _victim<Key> victim=_policy->victim();
                if (!victim) {
                    throw exception_cache_full("The cache is full and no element can be expired at the moment. Remove some elements manually");
                }
                this->_erase(*victim);
            }

            _policy->insert(_k);


            bool result=_storage.insert(value_type(_k,_d)).second;
            if (result) {
                _currEntries++;
            }

            return result;
        }
示例#7
0
 /*!
  * \brief Insert new element to the cache or replace value of the existing one
  *
  * Will check, whether element with the specified key exists in the map and, in case it exists, will update it's value and increase reference count of the element.
  *
  * Otherwise it will insert single new element. This effectively increases the cache size. Because cache do not allow for duplicate key values, the insertion operation checks 
  * for each element inserted whether another element exists already in the container with the same key value, if so, the element is not inserted and its mapped value is not changed in any way.
  * Extension of cache could result in removal of some elements, depending of the cache fullness and used policy. It is also possible, that removal of excessive entries
  * will fail, therefore insert operation will fail too.
  *
  * \throw <exception_cache_full>  Thrown when there are no available space in the cache and policy doesn't allows removal of elements.
  * \throw <exception_invalid_key> Thrown when the policy doesn't accepts the key
  *
  * \return true if the new elemented was inserted or false if an element with the same key existed.
  */
 bool insert_or_assign(Key _k, Data _d) {
     if(this->_storage.find(_k)==this->_storage.end()){
         this->insert(_k, _d);
         return true;
     }
     
     _policy->touch(_k);
     _storage.erase(_k);
     _storage.insert(value_type(_k,_d)).second;
     return false;
 }
示例#8
0
        /*!
         * \brief Swaps contents of two caches
         *
         * Exchanges the content of the cache with the content of mp, which is another cache object containing elements of the same type and using the same expiration policy.
         * Sizes may differ. Maximum number of entries may differ too.
         *
         * \param <mp> Another cache of the same type as this whose cache is swapped with that of this cache.
         *
         * \throw <exception_invalid_policy> Thrown when the policies of the caches to swap are incompatible.
         *
         * \see cache::operator=
         */
        void swap ( cache<Key,Data,Policy,Compare,Allocator>& mp ) {
            write_lock_type l = lock.lockWrite();
            _storage.swap(mp._storage);
            _policy->swap(*mp._policy);

            std::size_t m=this->_maxEntries;
            this->_maxEntries=mp._maxEntries;
            mp._maxEntries=m;

            this->_currEntries=this->_size();
            mp._currEntries=mp.size();
        }
示例#9
0
  KOKKOS_INLINE_FUNCTION
  void operator()( typename policy_type::member_type & , value_type & result )
    {
#if 0
      printf( "\nTestFib(%ld) %d %d\n"
             , n
             , int( ! fib_m1.is_null() )
             , int( ! fib_m2.is_null() )
             );
#endif

      if ( n < 2 ) {
        result = n ;
      }
      else if ( ! fib_m2.is_null() && ! fib_m1.is_null() ) {
        result = fib_m1.get() + fib_m2.get();
      }
      else {

        // Spawn new children and respawn myself to sum their results:
        // Spawn lower value at higher priority as it has a shorter
        // path to completion.

        fib_m2 = policy.task_spawn( TestFib(policy,n-2)
                                  , Kokkos::TaskSingle
                                  , Kokkos::TaskHighPriority );

        fib_m1 = policy.task_spawn( TestFib(policy,n-1)
                                  , Kokkos::TaskSingle );

        Kokkos::Future<Space> dep[] = { fib_m1 , fib_m2 };

        Kokkos::Future<Space> fib_all = policy.when_all( 2 , dep );

        if ( ! fib_m2.is_null() && ! fib_m1.is_null() && ! fib_all.is_null() ) {
          // High priority to retire this branch
          policy.respawn( this , Kokkos::TaskHighPriority , fib_all );
        }
        else {
#if 0
      printf( "TestFib(%ld) insufficient memory alloc_capacity(%d) task_max(%d) task_accum(%ld)\n"
             , n
             , policy.allocation_capacity()
             , policy.allocated_task_count_max()
             , policy.allocated_task_count_accum()
             );
#endif
          Kokkos::abort("TestFib insufficient memory");

        }
      }
    }
示例#10
0
    typename std::enable_if< ! std::is_same<policy_type,PRIORITY_POLICY>::value, std::future<typename std::result_of<F(Args...)>::type> >::type
    enqueue(F&& f, Args&&... args){
        typedef typename std::result_of<F(Args...)>::type return_type;
        // Don't allow enqueueing after stopping the pool
        if ( ! isActive.load() )
            throw std::runtime_error("enqueue on stopped ThreadPool");

        auto task = std::make_shared<std::packaged_task<return_type()>>(
            std::bind(std::forward<F>(f), std::forward<Args>(args)...) );

        std::future<return_type> result = task->get_future();
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            mTasks.push([task](){ (*task)(); });
        }
        condition.notify_one();
        return result;
    }
示例#11
0
 static 
 void addDependence(policy_type &policy, 
                    TaskFunctorType *after, const future_type &before) {
   policy.add_dependence(after, before);
 }
示例#12
0
 static  KOKKOS_INLINE_FUNCTION
 void clearDependence(policy_type &policy, TaskFunctorType *func) {
   policy.clear_dependence(func);
 }
示例#13
0
 /*!
  * \brief Increase usage count for entry
  *
  *  Touches an entry in cache, simulating access to it. Usefull to promote (or devote, depending on policy) item in the cache, reducing(or increasing)
  *  risk for expiration for it.
  *
  *  \param _k key to touch
  *
  */
 void touch(const Key& _k) {
     write_lock_type l = lock.lockWrite();
     _policy->touch(_k);
 }
示例#14
0
 const bool _check(const Key& _k) throw() {
     _policy->touch(_k);
     return _storage.count(_k)==1;
 }
示例#15
0
 static
 void respawn(policy_type &policy, TaskFunctorType *func) {
   policy.respawn(func);
 }
示例#16
0
 static 
 void clearDependence(policy_type &policy, TaskFunctorType *func) {
   policy.clear_dependence(func);
 }
示例#17
0
 static
 void spawn(policy_type &policy, const future_type &obj) {
   policy.spawn(obj);
 }
示例#18
0
 static 
 future_type create(policy_type &policy, const TaskFunctorType &func) {
   return (_use_team_interface ? 
           policy.create_team(func, _max_task_dependence) : 
           policy.create     (func, _max_task_dependence)); 
 }
示例#19
0
 static
 void addDependence(policy_type &policy, 
                    const future_type &after, const future_type &before) {
   policy.add_dependence(after, before);
 }
示例#20
0
 /*!
  * \brief Clear the cache
  *
  * Removes all cache entries, drops all usage count data and so on.
  *
  * \see size
  * \see empty
  *
  */
 void clear() {
     write_lock_type l = lock.lockWrite();
     _storage.clear();
     _policy->clear();
     this->_currEntries=0;
 }
示例#21
0
 static KOKKOS_INLINE_FUNCTION
 void respawn(policy_type &policy, TaskFunctorType *func) {
   policy.respawn(func);
 }
示例#22
0
 static KOKKOS_INLINE_FUNCTION
 void spawn(policy_type &policy, const future_type &obj, bool priority = false ) {
   policy.spawn(obj,priority);
 }
示例#23
0
 static  KOKKOS_INLINE_FUNCTION
 void addDependence(policy_type &policy, 
                    TaskFunctorType *after, const future_type &before) {
   policy.add_dependence(after, before);
 }