Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_Random_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Tpetra: Templated Linear Algebra Services Package
4 //
5 // Copyright 2008 NTESS and the Tpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TPETRA_DETAILS_RANDOM_DEF_HPP
11 #define TPETRA_DETAILS_RANDOM_DEF_HPP
12 
13 #include "Tpetra_Details_Random_decl.hpp"
14 #include "Teuchos_TestForException.hpp"
15 #include "Kokkos_Random.hpp"
16 
17 namespace Tpetra {
18 namespace Details {
19 
20 namespace { //anonymous
21 template<class ExecutionSpace>
22 void finalize_pool() {
23  using PoolClass = Static_Random_XorShift64_Pool<ExecutionSpace>;
24  if(PoolClass::pool_ != nullptr) {
25  delete PoolClass::pool_;
26  }
27  PoolClass::pool_=nullptr;
28 }
29 }// end namespace
30 
31 
32 
33 template<class ExecutionSpace>
34 unsigned int Static_Random_XorShift64_Pool<ExecutionSpace>::getSeedFromRank(int mpi_rank) {
35  // Seed the pseudorandom number generator using the calling
36  // process' rank. This helps decorrelate different process'
37  // pseudorandom streams. It's not perfect but it's effective and
38  // doesn't require MPI communication. The seed also includes bits
39  // from the standard library's rand().
40  uint64_t myRank =static_cast<uint64_t>(mpi_rank);
41  uint64_t seed64 = static_cast<uint64_t> (std::rand ()) + myRank + 17311uLL;
42  unsigned int seed = static_cast<unsigned int> (seed64&0xffffffff);
43  return seed;
44 }
45 
46 
47 template<class ExecutionSpace>
48 void Static_Random_XorShift64_Pool<ExecutionSpace>::
49 resetPool(int mpi_rank) {
50  using pool_type = Kokkos::Random_XorShift64_Pool<ExecutionSpace>;
51 
52  if(isSet())
53  delete pool_;
54  else
55  Kokkos::push_finalize_hook(finalize_pool<ExecutionSpace>);
56 
57  pool_ = new Kokkos::Random_XorShift64_Pool<ExecutionSpace>(getSeedFromRank(mpi_rank));
58 }
59 
60 template<class ExecutionSpace>
61 bool Static_Random_XorShift64_Pool<ExecutionSpace>::
62 isSet() {
63  return pool_!=nullptr;
64 }
65 
66 template<class ExecutionSpace>
67 Kokkos::Random_XorShift64_Pool<ExecutionSpace> & Static_Random_XorShift64_Pool<ExecutionSpace>::
68 getPool() {
69  TEUCHOS_TEST_FOR_EXCEPTION(!isSet(),std::runtime_error,"Tpetra::Details::Static_Random_XorShift64_Pool: resetPool() must be called before getPool");
70  return *pool_;
71 }
72 
73 
74 } // namespace Details
75 } // namespace Tpetra
76 
77 
78 //
79 // Explicit instantiation macro
80 //
81 // Must be expanded from within the Tpetra namespace!
82 // NOTE: Tpetra::Details::Random is templated on execution space,
83 // but we can use this trick to get it out of the node.
84 //
85 
86 #define TPETRA_DETAILS_RANDOM_INSTANT(NODE) \
87  template<> Kokkos::Random_XorShift64_Pool<typename NODE::execution_space>* Details::Static_Random_XorShift64_Pool<typename NODE::execution_space>::pool_ = nullptr; \
88  template class Details::Static_Random_XorShift64_Pool<typename NODE::execution_space>;
89 
90 
91 
92 #endif // TPETRA_DETAILS_RANDOM_DEF_HPP