17#ifndef __algo_stochastic_threaded_loop_h__
18#define __algo_stochastic_threaded_loop_h__
36 template <
int N,
class Functor,
class... ImageType>
37 struct StochasticThreadedLoopRunInner
38 {
MEMALIGN(StochasticThreadedLoopRunInner<N,Functor,ImageType...>)
39 const vector<size_t>& outer_axes;
40 decltype (
Loop (outer_axes)) loop;
41 typename std::remove_reference<Functor>::type func;
43 Math::RNG::Uniform<double>
rng;
44 std::tuple<ImageType...> vox;
46 StochasticThreadedLoopRunInner (
const vector<size_t>& outer_axes,
const vector<size_t>& inner_axes,
47 const Functor&
functor,
const double voxel_density, ImageType&... voxels) :
48 outer_axes (outer_axes),
49 loop (
Loop (inner_axes)),
51 density (voxel_density),
52 rng (Math::RNG::Uniform<double>()),
55 void operator() (
const Iterator& pos) {
56 assign_pos_of (pos, outer_axes).to (vox);
57 for (
auto i =
unpack (loop, vox); i; ++i) {
58 if (
rng() >= density){
69 template <
class Functor,
class... ImageType>
70 struct StochasticThreadedLoopRunInner<0,Functor,ImageType...>
71 {
MEMALIGN(StochasticThreadedLoopRunInner<0, Functor,ImageType...>)
72 const vector<size_t>& outer_axes;
73 decltype (
Loop (outer_axes)) loop;
74 typename std::remove_reference<Functor>::type func;
76 Math::RNG::Uniform<double>
rng;
79 StochasticThreadedLoopRunInner (
const vector<size_t>& outer_axes,
const vector<size_t>& inner_axes,
80 const Functor&
functor,
const double voxel_density, ImageType&... voxels) :
81 outer_axes (outer_axes),
82 loop (
Loop (inner_axes)),
84 density (voxel_density),
85 rng (Math::RNG::Uniform<double>()) { }
87 void operator() (Iterator& pos) {
88 for (
auto i = loop (pos); i; ++i){
89 if (
rng() >= density){
100 template <
class OuterLoopType>
101 struct StochasticThreadedLoopRunOuter {
MEMALIGN(StochasticThreadedLoopRunOuter<OuterLoopType>)
103 OuterLoopType outer_loop;
104 vector<size_t> inner_axes;
107 template <
class Functor>
108 void run_outer (Functor&&
functor,
const double voxel_density)
111 for (
auto i = outer_loop (iterator); i; ++i){
120 decltype (outer_loop (iterator)) loop;
123 std::lock_guard<std::mutex> lock (mutex);
125 assign_pos_of (iterator, loop.axes).to (pos);
131 } shared = { iterator, outer_loop (iterator) };
133 struct PerThread {
MEMALIGN(PerThread)
135 typename std::remove_reference<Functor>::type func;
137 Iterator pos = shared.iterator;
138 while (shared.next (pos))
141 } loop_thread = { shared,
functor };
149 template <
class Functor,
class... ImageType>
150 void run (Functor&&
functor,
const double voxel_density, ImageType&&... vox)
152 StochasticThreadedLoopRunInner<
153 sizeof...(ImageType),
154 typename std::remove_reference<Functor>::type,
155 typename std::remove_reference<ImageType>::type...
156 > loop_thread (outer_loop.axes, inner_axes,
functor, voxel_density, vox...);
157 run_outer (loop_thread, voxel_density);
170 template <
class HeaderType>
172 const HeaderType& source,
175 return { source,
Loop (outer_axes), inner_axes };
179 template <
class HeaderType>
181 const HeaderType& source,
183 size_t num_inner_axes = 1) {
184 return { source,
Loop (get_outer_axes (axes, num_inner_axes)), get_inner_axes (axes, num_inner_axes) };
187 template <
class HeaderType>
189 const HeaderType& source,
190 size_t from_axis = 0,
191 size_t to_axis = std::numeric_limits<size_t>::max(),
192 size_t num_inner_axes = 1) {
194 Loop (get_outer_axes (source, num_inner_axes, from_axis, to_axis)),
195 get_inner_axes (source, num_inner_axes, from_axis, to_axis) };
198 template <
class HeaderType>
200 const std::string& progress_message,
201 const HeaderType& source,
204 return { source,
Loop (progress_message, outer_axes), inner_axes };
207 template <
class HeaderType>
209 const std::string& progress_message,
210 const HeaderType& source,
212 size_t num_inner_axes = 1) {
214 Loop (progress_message, get_outer_axes (axes, num_inner_axes)),
215 get_inner_axes (axes, num_inner_axes) };
218 template <
class HeaderType>
220 const std::string& progress_message,
221 const HeaderType& source,
222 size_t from_axis = 0,
223 size_t to_axis = std::numeric_limits<size_t>::max(),
224 size_t num_inner_axes = 1) {
226 Loop (progress_message, get_outer_axes (source, num_inner_axes, from_axis, to_axis)),
227 get_inner_axes (source, num_inner_axes, from_axis, to_axis) };
FORCE_INLINE LoopAlongAxes Loop()
__run< Functor >::type run(Functor &&functor, const std::string &name="unnamed")
Execute the functor's execute method in a separate thread.
size_t threads_to_execute()
__Multi< typename std::remove_reference< Functor >::type > multi(Functor &&functor, size_t nthreads=threads_to_execute())
used to request multiple threads of the corresponding functor
thread_local Math::RNG rng
thread-local, but globally accessible RNG to vastly simplify multi-threading
auto unpack(F &&f, T &&t) -> decltype(Unpack< ::std::tuple_size< typename ::std::decay< T >::type >::value >::unpack(::std::forward< F >(f), ::std::forward< T >(t)))
if t is a tuple of elements a..., invoke f(a...)
void check_app_exit_code()
StochasticThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> StochasticThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
std::remove_reference< Functor >::type & functor