|
Kokkos Core Kernels Package
Version of the Day
|
00001 /* 00002 //@HEADER 00003 // ************************************************************************ 00004 // 00005 // Kokkos: Manycore Performance-Portable Multidimensional Arrays 00006 // Copyright (2012) Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov) 00039 // 00040 // ************************************************************************ 00041 //@HEADER 00042 */ 00043 00044 #ifndef KOKKOS_BITSET_HPP 00045 #define KOKKOS_BITSET_HPP 00046 00047 #include <Kokkos_Core.hpp> 00048 #include <Kokkos_Functional.hpp> 00049 00050 #include <impl/Kokkos_Bitset_impl.hpp> 00051 00052 #include <stdexcept> 00053 00054 namespace Kokkos { 00055 00056 template <typename Device = Kokkos::DefaultExecutionSpace > 00057 class Bitset; 00058 00059 template <typename Device = Kokkos::DefaultExecutionSpace > 00060 class ConstBitset; 00061 00062 template <typename DstDevice, typename SrcDevice> 00063 void deep_copy( Bitset<DstDevice> & dst, Bitset<SrcDevice> const& src); 00064 00065 template <typename DstDevice, typename SrcDevice> 00066 void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src); 00067 00068 template <typename DstDevice, typename SrcDevice> 00069 void deep_copy( ConstBitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src); 00070 00071 00073 template <typename Device> 00074 class Bitset 00075 { 00076 public: 00077 typedef Device device_type; 00078 typedef unsigned size_type; 00079 00080 enum { BIT_SCAN_REVERSE = 1u }; 00081 enum { MOVE_HINT_BACKWARD = 2u }; 00082 00083 enum { 00084 BIT_SCAN_FORWARD_MOVE_HINT_FORWARD = 0u 00085 , BIT_SCAN_REVERSE_MOVE_HINT_FORWARD = BIT_SCAN_REVERSE 00086 , BIT_SCAN_FORWARD_MOVE_HINT_BACKWARD = MOVE_HINT_BACKWARD 00087 , BIT_SCAN_REVERSE_MOVE_HINT_BACKWARD = BIT_SCAN_REVERSE | MOVE_HINT_BACKWARD 00088 }; 00089 00090 private: 00091 enum { block_size = static_cast<unsigned>(sizeof(unsigned)*CHAR_BIT) }; 00092 enum { block_mask = block_size-1u }; 00093 enum { block_shift = static_cast<int>(Impl::power_of_two<block_size>::value) }; 00094 00095 public: 00096 00097 00100 Bitset(unsigned arg_size = 0u) 00101 : m_size(arg_size) 00102 , m_last_block_mask(0u) 00103 , m_blocks("Bitset", ((m_size + block_mask) >> block_shift) ) 00104 { 00105 for (int i=0, end = static_cast<int>(m_size & block_mask); i < end; ++i) { 00106 m_last_block_mask |= 1u << i; 00107 } 00108 } 00109 00111 Bitset<Device> & operator = (Bitset<Device> const & rhs) 00112 { 00113 this->m_size = rhs.m_size; 00114 this->m_last_block_mask = rhs.m_last_block_mask; 00115 this->m_blocks = rhs.m_blocks; 00116 00117 return *this; 00118 } 00119 00121 Bitset( Bitset<Device> const & rhs) 00122 : m_size( rhs.m_size ) 00123 , m_last_block_mask( rhs.m_last_block_mask ) 00124 , m_blocks( rhs.m_blocks ) 00125 {} 00126 00129 KOKKOS_FORCEINLINE_FUNCTION 00130 unsigned size() const 00131 { return m_size; } 00132 00135 unsigned count() const 00136 { 00137 Impl::BitsetCount< Bitset<Device> > f(*this); 00138 return f.apply(); 00139 } 00140 00143 void set() 00144 { 00145 Kokkos::deep_copy(m_blocks, ~0u ); 00146 00147 if (m_last_block_mask) { 00148 //clear the unused bits in the last block 00149 typedef Kokkos::Impl::DeepCopy< typename device_type::memory_space, Kokkos::HostSpace > raw_deep_copy; 00150 raw_deep_copy( m_blocks.ptr_on_device() + (m_blocks.size() -1u), &m_last_block_mask, sizeof(unsigned)); 00151 } 00152 } 00153 00156 void reset() 00157 { 00158 Kokkos::deep_copy(m_blocks, 0u ); 00159 } 00160 00163 void clear() 00164 { 00165 Kokkos::deep_copy(m_blocks, 0u ); 00166 } 00167 00170 KOKKOS_FORCEINLINE_FUNCTION 00171 bool set( unsigned i ) const 00172 { 00173 if ( i < m_size ) { 00174 unsigned * block_ptr = &m_blocks[ i >> block_shift ]; 00175 const unsigned mask = 1u << static_cast<int>( i & block_mask ); 00176 00177 return !( atomic_fetch_or( block_ptr, mask ) & mask ); 00178 } 00179 return false; 00180 } 00181 00184 KOKKOS_FORCEINLINE_FUNCTION 00185 bool reset( unsigned i ) const 00186 { 00187 if ( i < m_size ) { 00188 unsigned * block_ptr = &m_blocks[ i >> block_shift ]; 00189 const unsigned mask = 1u << static_cast<int>( i & block_mask ); 00190 00191 return atomic_fetch_and( block_ptr, ~mask ) & mask; 00192 } 00193 return false; 00194 } 00195 00198 KOKKOS_FORCEINLINE_FUNCTION 00199 bool test( unsigned i ) const 00200 { 00201 if ( i < m_size ) { 00202 const unsigned block = volatile_load(&m_blocks[ i >> block_shift ]); 00203 const unsigned mask = 1u << static_cast<int>( i & block_mask ); 00204 return block & mask; 00205 } 00206 return false; 00207 } 00208 00212 KOKKOS_FORCEINLINE_FUNCTION 00213 unsigned max_hint() const 00214 { 00215 return m_blocks.size(); 00216 } 00217 00221 KOKKOS_INLINE_FUNCTION 00222 Kokkos::pair<bool, unsigned> find_any_set_near( unsigned hint , unsigned scan_direction = BIT_SCAN_FORWARD_MOVE_HINT_FORWARD ) const 00223 { 00224 const unsigned block_idx = (hint >> block_shift) < m_blocks.size() ? (hint >> block_shift) : 0; 00225 const unsigned offset = hint & block_mask; 00226 unsigned block = volatile_load(&m_blocks[ block_idx ]); 00227 block = !m_last_block_mask || (block_idx < (m_blocks.size()-1)) ? block : block & m_last_block_mask ; 00228 00229 return find_any_helper(block_idx, offset, block, scan_direction); 00230 } 00231 00235 KOKKOS_INLINE_FUNCTION 00236 Kokkos::pair<bool, unsigned> find_any_unset_near( unsigned hint , unsigned scan_direction = BIT_SCAN_FORWARD_MOVE_HINT_FORWARD ) const 00237 { 00238 const unsigned block_idx = hint >> block_shift; 00239 const unsigned offset = hint & block_mask; 00240 unsigned block = volatile_load(&m_blocks[ block_idx ]); 00241 block = !m_last_block_mask || (block_idx < (m_blocks.size()-1) ) ? ~block : ~block & m_last_block_mask ; 00242 00243 return find_any_helper(block_idx, offset, block, scan_direction); 00244 } 00245 00246 private: 00247 00248 KOKKOS_FORCEINLINE_FUNCTION 00249 Kokkos::pair<bool, unsigned> find_any_helper(unsigned block_idx, unsigned offset, unsigned block, unsigned scan_direction) const 00250 { 00251 Kokkos::pair<bool, unsigned> result( block > 0u, 0); 00252 00253 if (!result.first) { 00254 result.second = update_hint( block_idx, offset, scan_direction ); 00255 } 00256 else { 00257 result.second = scan_block( (block_idx << block_shift) 00258 , offset 00259 , block 00260 , scan_direction 00261 ); 00262 } 00263 return result; 00264 } 00265 00266 00267 KOKKOS_FORCEINLINE_FUNCTION 00268 unsigned scan_block(unsigned block_start, int offset, unsigned block, unsigned scan_direction ) const 00269 { 00270 offset = !(scan_direction & BIT_SCAN_REVERSE) ? offset : (offset + block_mask) & block_mask; 00271 block = Impl::rotate_right(block, offset); 00272 return ((( !(scan_direction & BIT_SCAN_REVERSE) ? 00273 Impl::bit_scan_forward(block) : 00274 Impl::bit_scan_reverse(block) 00275 ) + offset 00276 ) & block_mask 00277 ) + block_start; 00278 } 00279 00280 KOKKOS_FORCEINLINE_FUNCTION 00281 unsigned update_hint( long long block_idx, unsigned offset, unsigned scan_direction ) const 00282 { 00283 block_idx += scan_direction & MOVE_HINT_BACKWARD ? -1 : 1; 00284 block_idx = block_idx >= 0 ? block_idx : m_blocks.size() - 1; 00285 block_idx = block_idx < static_cast<long long>(m_blocks.size()) ? block_idx : 0; 00286 00287 return static_cast<unsigned>(block_idx)*block_size + offset; 00288 } 00289 00290 private: 00291 00292 unsigned m_size; 00293 unsigned m_last_block_mask; 00294 View< unsigned *, device_type, MemoryTraits<RandomAccess> > m_blocks; 00295 00296 private: 00297 template <typename DDevice> 00298 friend class Bitset; 00299 00300 template <typename DDevice> 00301 friend class ConstBitset; 00302 00303 template <typename Bitset> 00304 friend struct Impl::BitsetCount; 00305 00306 template <typename DstDevice, typename SrcDevice> 00307 friend void deep_copy( Bitset<DstDevice> & dst, Bitset<SrcDevice> const& src); 00308 00309 template <typename DstDevice, typename SrcDevice> 00310 friend void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src); 00311 }; 00312 00315 template <typename Device> 00316 class ConstBitset 00317 { 00318 public: 00319 typedef Device device_type; 00320 typedef unsigned size_type; 00321 00322 private: 00323 enum { block_size = static_cast<unsigned>(sizeof(unsigned)*CHAR_BIT) }; 00324 enum { block_mask = block_size -1u }; 00325 enum { block_shift = static_cast<int>(Impl::power_of_two<block_size>::value) }; 00326 00327 public: 00328 ConstBitset() 00329 : m_size (0) 00330 {} 00331 00332 ConstBitset(Bitset<Device> const& rhs) 00333 : m_size(rhs.m_size) 00334 , m_blocks(rhs.m_blocks) 00335 {} 00336 00337 ConstBitset(ConstBitset<Device> const& rhs) 00338 : m_size( rhs.m_size ) 00339 , m_blocks( rhs.m_blocks ) 00340 {} 00341 00342 ConstBitset<Device> & operator = (Bitset<Device> const & rhs) 00343 { 00344 this->m_size = rhs.m_size; 00345 this->m_blocks = rhs.m_blocks; 00346 00347 return *this; 00348 } 00349 00350 ConstBitset<Device> & operator = (ConstBitset<Device> const & rhs) 00351 { 00352 this->m_size = rhs.m_size; 00353 this->m_blocks = rhs.m_blocks; 00354 00355 return *this; 00356 } 00357 00358 00359 KOKKOS_FORCEINLINE_FUNCTION 00360 unsigned size() const 00361 { 00362 return m_size; 00363 } 00364 00365 unsigned count() const 00366 { 00367 Impl::BitsetCount< ConstBitset<Device> > f(*this); 00368 return f.apply(); 00369 } 00370 00371 KOKKOS_FORCEINLINE_FUNCTION 00372 bool test( unsigned i ) const 00373 { 00374 if ( i < m_size ) { 00375 const unsigned block = m_blocks[ i >> block_shift ]; 00376 const unsigned mask = 1u << static_cast<int>( i & block_mask ); 00377 return block & mask; 00378 } 00379 return false; 00380 } 00381 00382 private: 00383 00384 unsigned m_size; 00385 View< const unsigned *, device_type, MemoryTraits<RandomAccess> > m_blocks; 00386 00387 private: 00388 template <typename DDevice> 00389 friend class ConstBitset; 00390 00391 template <typename Bitset> 00392 friend struct Impl::BitsetCount; 00393 00394 template <typename DstDevice, typename SrcDevice> 00395 friend void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src); 00396 00397 template <typename DstDevice, typename SrcDevice> 00398 friend void deep_copy( ConstBitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src); 00399 }; 00400 00401 00402 template <typename DstDevice, typename SrcDevice> 00403 void deep_copy( Bitset<DstDevice> & dst, Bitset<SrcDevice> const& src) 00404 { 00405 if (dst.size() != src.size()) { 00406 throw std::runtime_error("Error: Cannot deep_copy bitsets of different sizes!"); 00407 } 00408 00409 typedef Kokkos::Impl::DeepCopy< typename DstDevice::memory_space, typename SrcDevice::memory_space > raw_deep_copy; 00410 raw_deep_copy(dst.m_blocks.ptr_on_device(), src.m_blocks.ptr_on_device(), sizeof(unsigned)*src.m_blocks.size()); 00411 } 00412 00413 template <typename DstDevice, typename SrcDevice> 00414 void deep_copy( Bitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src) 00415 { 00416 if (dst.size() != src.size()) { 00417 throw std::runtime_error("Error: Cannot deep_copy bitsets of different sizes!"); 00418 } 00419 00420 typedef Kokkos::Impl::DeepCopy< typename DstDevice::memory_space, typename SrcDevice::memory_space > raw_deep_copy; 00421 raw_deep_copy(dst.m_blocks.ptr_on_device(), src.m_blocks.ptr_on_device(), sizeof(unsigned)*src.m_blocks.size()); 00422 } 00423 00424 template <typename DstDevice, typename SrcDevice> 00425 void deep_copy( ConstBitset<DstDevice> & dst, ConstBitset<SrcDevice> const& src) 00426 { 00427 if (dst.size() != src.size()) { 00428 throw std::runtime_error("Error: Cannot deep_copy bitsets of different sizes!"); 00429 } 00430 00431 typedef Kokkos::Impl::DeepCopy< typename DstDevice::memory_space, typename SrcDevice::memory_space > raw_deep_copy; 00432 raw_deep_copy(dst.m_blocks.ptr_on_device(), src.m_blocks.ptr_on_device(), sizeof(unsigned)*src.m_blocks.size()); 00433 } 00434 00435 } // namespace Kokkos 00436 00437 #endif //KOKKOS_BITSET_HPP
1.7.6.1