autodiffstackstorage.hpp
Go to the documentation of this file.
1 #ifndef STAN_MATH_REV_CORE_AUTODIFFSTACKSTORAGE_HPP
2 #define STAN_MATH_REV_CORE_AUTODIFFSTACKSTORAGE_HPP
3 
5 #include <vector>
6 
7 namespace stan {
8 namespace math {
9 
10 /**
11  * Provides a thread_local singleton if needed. Read warnings below!
12  * For performance reasons the singleton is a global static for the
13  * case of no threading which is returned by a function. This design
14  * should allow the compiler to apply necessary inlining to get
15  * maximal performance. However, this design suffers from "the static
16  * init order fiasco"[0]. Anywhere this is used, we must be
17  * absolutely positive that it doesn't matter when the singleton will
18  * get initialized relative to other static variables. In exchange,
19  * we get a more performant singleton pattern for the non-threading
20  * case. In the threading case we use the defacto standard C++11
21  * singleton pattern relying on a function wrapping a static local
22  * variable. This standard pattern is expected to be well supported
23  * by the major compilers (as its standard), but it does incur some
24  * performance penalty. There has been some discussion on this; see
25  * [1] and [2] and the discussions those PRs link to as well.
26  *
27  * These are thread_local only if the user asks for it with
28  * -DSTAN_THREADS. This is primarily because Apple clang compilers
29  * before 2016 don't support thread_local and the additional
30  * performance cost. We have proposed removing support for those[3],
31  * and at that time we should evaluate the performance of a switch to
32  * thread_local. If there is no loss in performance, we can remove
33  * this ifdef.
34  *
35  * [0] https://isocpp.org/wiki/faq/ctors#static-init-order
36  * [1] https://github.com/stan-dev/math/pull/840
37  * [2] https://github.com/stan-dev/math/pull/826
38  * [3]
39  * http://discourse.mc-stan.org/t/potentially-dropping-support-for-older-versions-of-apples-version-of-clang/3780/
40  */
41 template <typename ChainableT, typename ChainableAllocT>
45 
48 
49  std::vector<ChainableT *> var_stack_;
50  std::vector<ChainableT *> var_nochain_stack_;
51  std::vector<ChainableAllocT *> var_alloc_stack_;
53 
54  // nested positions
55  std::vector<size_t> nested_var_stack_sizes_;
56  std::vector<size_t> nested_var_nochain_stack_sizes_;
57  std::vector<size_t> nested_var_alloc_stack_starts_;
58  };
59 
60  AutodiffStackSingleton() = delete;
61  explicit AutodiffStackSingleton(AutodiffStackSingleton_t const &) = delete;
63 
64  static inline AutodiffStackStorage &instance() {
65 #ifdef STAN_THREADS
66  thread_local static AutodiffStackStorage instance_;
67 #endif
68  return instance_;
69  }
70 
71 #ifndef STAN_THREADS
72 
73  private:
75 #endif
76 };
77 
78 #ifndef STAN_THREADS
79 template <typename ChainableT, typename ChainableAllocT>
80 typename AutodiffStackSingleton<ChainableT,
81  ChainableAllocT>::AutodiffStackStorage
83 #endif
84 
85 } // namespace math
86 } // namespace stan
87 #endif
static AutodiffStackStorage instance_
AutodiffStackStorage & operator=(const AutodiffStackStorage &)=delete
AutodiffStackSingleton< ChainableT, ChainableAllocT > AutodiffStackSingleton_t
static AutodiffStackStorage & instance()