17#ifndef __algo_random_threaded_loop_h__
18#define __algo_random_threaded_loop_h__
36 template <
int N,
class Functor,
class... ImageType>
37 struct RandomThreadedLoopRunInner
38 {
MEMALIGN(RandomThreadedLoopRunInner<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 const vector<size_t> dims;
45 std::tuple<ImageType...> vox;
47 RandomThreadedLoopRunInner (
const vector<size_t>& outer_axes,
const vector<size_t>& inner_axes,
48 const Functor&
functor,
const double voxel_density,
const vector<size_t> dimensions, ImageType&... voxels) :
49 outer_axes (outer_axes),
50 loop (
Loop (inner_axes)),
52 density (voxel_density),
56 void operator() (
const Iterator& pos) {
57 assign_pos_of (pos, outer_axes).to (vox);
58 for (
auto i =
unpack (loop, vox); i; ++i) {
70 template <
class Functor,
class... ImageType>
71 struct RandomThreadedLoopRunInner<0,Functor,ImageType...>
72 {
MEMALIGN(RandomThreadedLoopRunInner<0,Functor,ImageType...>)
73 const vector<size_t>& outer_axes;
74 const vector<size_t> inner;
75 decltype (
Loop (outer_axes)) loop;
77 typename std::remove_reference<Functor>::type func;
82 std::default_random_engine random_engine;
84 vector<size_t>::iterator it;
85 vector<size_t>::iterator stop;
86 const vector<size_t> dims;
94 RandomThreadedLoopRunInner (
const vector<size_t>& outer_axes,
const vector<size_t>& inner_axes,
95 const Functor&
functor,
const double voxel_density,
const vector<size_t>& dimensions, ImageType&... voxels) :
96 outer_axes (outer_axes),
98 loop (
Loop (inner_axes)),
100 density (voxel_density),
102 assert (inner_axes.size() == 1);
106 typename std::default_random_engine::result_type seed =
rng.
get_seed();
107 random_engine = std::default_random_engine{
static_cast<std::default_random_engine::result_type
>(seed)};
108 idx = vector<size_t>(dims[inner_axes[0]]);
109 std::iota (std::begin(idx), std::end(idx), 0);
112 void operator() (Iterator& pos) {
113 std::shuffle (std::begin(idx), std::end(idx), random_engine);
115 it = std::begin(idx);
116 stop = std::end(idx);
118 (size_t)
std::ceil (density * dims[inner[0]]);
120 for (
size_t i = 0; i < max_cnt; ++i){
121 pos.index(inner[0]) = *it;
134 pos.index(inner[0]) = dims[inner[0]];
140 template <
class OuterLoopType>
141 struct RandomThreadedLoopRunOuter {
MEMALIGN(RandomThreadedLoopRunOuter<OuterLoopType>)
143 OuterLoopType outer_loop;
144 vector<size_t> inner_axes;
147 template <
class Functor>
148 void run_outer (Functor&&
functor,
const double voxel_density,
const vector<size_t>& dimensions)
151 for (
auto i = outer_loop (iterator); i; ++i){
160 decltype (outer_loop (iterator)) loop;
163 std::lock_guard<std::mutex> lock (mutex);
165 assign_pos_of (iterator, loop.axes).to (pos);
171 } shared = { iterator, outer_loop (iterator) };
173 struct PerThread {
MEMALIGN(PerThread)
175 typename std::remove_reference<Functor>::type func;
177 Iterator pos = shared.iterator;
178 while (shared.next (pos))
181 } loop_thread = { shared,
functor };
189 template <
class Functor,
class... ImageType>
190 void run (Functor&&
functor,
const double voxel_density, vector<size_t> dimensions, ImageType&&... vox)
192 RandomThreadedLoopRunInner<
193 sizeof...(ImageType),
194 typename std::remove_reference<Functor>::type,
195 typename std::remove_reference<ImageType>::type...
196 > loop_thread (outer_loop.axes, inner_axes,
functor, voxel_density, dimensions, vox...);
197 run_outer (loop_thread, voxel_density, dimensions);
210 template <
class HeaderType>
212 const HeaderType& source,
215 return { source,
Loop (outer_axes), inner_axes };
219 template <
class HeaderType>
221 const HeaderType& source,
223 size_t num_inner_axes = 1) {
224 return { source,
Loop (get_outer_axes (axes, num_inner_axes)), get_inner_axes (axes, num_inner_axes) };
227 template <
class HeaderType>
229 const HeaderType& source,
230 size_t from_axis = 0,
231 size_t to_axis = std::numeric_limits<size_t>::max(),
232 size_t num_inner_axes = 1) {
234 Loop (get_outer_axes (source, num_inner_axes, from_axis, to_axis)),
235 get_inner_axes (source, num_inner_axes, from_axis, to_axis) };
238 template <
class HeaderType>
240 const std::string& progress_message,
241 const HeaderType& source,
244 return { source,
Loop (progress_message, outer_axes), inner_axes };
247 template <
class HeaderType>
249 const std::string& progress_message,
250 const HeaderType& source,
252 size_t num_inner_axes = 1) {
254 Loop (progress_message, get_outer_axes (axes, num_inner_axes)),
255 get_inner_axes (axes, num_inner_axes) };
258 template <
class HeaderType>
260 const std::string& progress_message,
261 const HeaderType& source,
262 size_t from_axis = 0,
263 size_t to_axis = std::numeric_limits<size_t>::max(),
264 size_t num_inner_axes = 1) {
266 Loop (progress_message, get_outer_axes (source, num_inner_axes, from_axis, to_axis)),
267 get_inner_axes (source, num_inner_axes, from_axis, to_axis) };
static std::mt19937::result_type get_seed()
constexpr I ceil(const T x)
template function with cast to different type
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
RandomThreadedLoopRunOuter< decltype(Loop(vector< size_t >()))> RandomThreadedLoop(const HeaderType &source, const vector< size_t > &outer_axes, const vector< size_t > &inner_axes)
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()
std::remove_reference< Functor >::type & functor