/* //@HEADER // ************************************************************************ // // Kokkos v. 3.0 // Copyright (2020) National Technology & Engineering // Solutions of Sandia, LLC (NTESS). // // Under the terms of Contract DE-NA0003525 with NTESS, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact Christian R. Trott (crtrott@sandia.gov) // // ************************************************************************ //@HEADER */ #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE #include #ifndef KOKKOS_ENABLE_DEPRECATED_CODE_3 static_assert(false, "Including non-public Kokkos header files is not allowed."); #else KOKKOS_IMPL_WARNING("Including non-public Kokkos header files is not allowed.") #endif #endif #ifndef KOKKOS_UNIQUE_TOKEN_HPP #define KOKKOS_UNIQUE_TOKEN_HPP #include #include #include namespace Kokkos { namespace Experimental { enum class UniqueTokenScope : int { Instance, Global }; /// \brief class to generate unique ids base on the required amount of /// concurrency /// /// This object should behave like a ref-counted object, so that when the last /// instance is destroy resources are free if needed template class UniqueToken { public: using execution_space = ExecutionSpace; using size_type = typename execution_space::size_type; /// \brief create object size for concurrency on the given instance /// /// This object should not be shared between instances UniqueToken(execution_space const& = execution_space()); /// \brief upper bound for acquired values, i.e. 0 <= value < size() KOKKOS_INLINE_FUNCTION size_type size() const; /// \brief acquire value such that 0 <= value < size() KOKKOS_INLINE_FUNCTION size_type acquire() const; /// \brief release a value acquired by generate KOKKOS_INLINE_FUNCTION void release(size_type) const; }; /// \brief Instance scope UniqueToken allows for a max size other than /// execution_space::concurrency() /// /// This object should behave like a ref-counted object, so that when the last /// instance is destroyed, resources are free if needed template class UniqueToken : public UniqueToken { public: using execution_space = ExecutionSpace; using size_type = typename execution_space::size_type; /// \brief Create object with specified size /// /// It is required that max_size is >= the maximum number of concurrent /// threads that will attempt to acquire the UniqueToken. This constructor is /// most commonly useful when you: /// 1) Have a loop bound that may be smaller than /// execution_space::concurrency(). /// 2) Want a per-team unique token in the range [0, /// execution_space::concurrency() / team_size) UniqueToken(size_type max_size, execution_space const& = execution_space()); }; // NOTE There was an agreement amongst developers that "AcquireUniqueToken" is a // bad name but at this time no one has suggested a better alternative. /// \brief RAII helper for per-thread unique token values. /// /// The token value will be acquired at construction and automatically /// released at destruction. template class AcquireUniqueToken { public: using exec_space = ExecutionSpace; using size_type = typename exec_space::size_type; using token_type = UniqueToken; private: token_type my_token; size_type my_acquired_val; public: KOKKOS_FUNCTION AcquireUniqueToken(token_type t) : my_token(t), my_acquired_val(my_token.acquire()) {} KOKKOS_FUNCTION ~AcquireUniqueToken() { my_token.release(my_acquired_val); } KOKKOS_FUNCTION size_type value() const { return my_acquired_val; } }; /// \brief RAII helper for per-team unique token values. /// /// The token value will be acquired at construction and automatically /// released at destruction. All threads in a team will share the same /// token value. template class AcquireTeamUniqueToken { public: using exec_space = typename TeamPolicy::execution_space; using token_type = UniqueToken; using size_type = typename token_type::size_type; using team_member_type = typename TeamPolicy::member_type; using scratch_view = Kokkos::View; private: token_type my_token; size_type my_acquired_val; scratch_view my_team_acquired_val; team_member_type my_team; public: // NOTE The implementations of the constructor and destructor use // `Kokkos::single()` which is an inline function defined in each backend. // This creates circular dependency issues. Moving them to a separate header // is less than ideal and should be revisited later. Having a `UniqueToken` // forward declaration was considered but the non-type template parameter // makes things complicated because it would require moving the definition of // `UniqueTokenScope` enumeration type and its enumerators away which would // hurt readability. KOKKOS_FUNCTION AcquireTeamUniqueToken(token_type t, team_member_type team); KOKKOS_FUNCTION ~AcquireTeamUniqueToken(); KOKKOS_FUNCTION size_type value() const { return my_acquired_val; } static std::size_t shmem_size() { return scratch_view::shmem_size(); } }; } // namespace Experimental } // namespace Kokkos #endif // KOKKOS_UNIQUE_TOKEN_HPP