tatami_r
R bindings to tatami matrices
Loading...
Searching...
No Matches
parallelize.hpp
Go to the documentation of this file.
1#ifndef TATAMI_R_PARALLELIZE_HPP
2#define TATAMI_R_PARALLELIZE_HPP
3
7#ifdef TATAMI_R_PARALLELIZE_UNKNOWN
13#include "sanisizer/sanisizer.hpp"
14
15#include <thread>
16#include <cmath>
17#include <vector>
18#include <string>
19#include <stdexcept>
20#include <algorithm>
21
28namespace tatami_r {
29
33inline manticore::Executor* executor_ptr = NULL;
47 if (executor_ptr) {
48 return *executor_ptr;
49 } else {
50 // In theory, this should end up resolving to a single instance, even across dynamically linked libraries:
51 // https://stackoverflow.com/questions/52851239/local-static-variable-linkage-in-a-template-class-static-member-function
52 // In practice, this doesn't seem to be the case on a Mac, requiring us to use `set_executor()`.
53 static manticore::Executor mexec;
54 return mexec;
55 }
56}
57
66 executor_ptr = ptr;
67}
68
96template<class Function_, class Index_>
97int parallelize(const Function_ fun, const Index_ tasks, int threads) {
98 if (tasks == 0) {
99 return 0;
100 }
101
102 if (threads <= 1 || tasks == 1) {
103 fun(0, 0, tasks);
104 return 1;
105 }
106
107 Index_ tasks_per_worker = tasks / threads;
108 int remainder = tasks % threads;
109 if (tasks_per_worker == 0) {
110 tasks_per_worker = 1;
111 remainder = 0;
112 threads = tasks;
113 }
114
115 auto& mexec = executor();
116 mexec.initialize(threads, "failed to execute R command");
117
118 std::vector<std::thread> runners;
119 sanisizer::reserve(runners, threads);
120 auto errors = sanisizer::create<std::vector<std::exception_ptr> >(threads);
121
122 Index_ start = 0;
123 for (int w = 0; w < threads; ++w) {
124 Index_ length = tasks_per_worker + (w < remainder);
125
126 runners.emplace_back(
127 [&](const int id, const Index_ s, const Index_ l) -> void {
128 try {
129 fun(id, s, l);
130 } catch (...) {
131 errors[id] = std::current_exception();
132 }
133 mexec.finish_thread();
134 },
135 w,
136 start,
137 length
138 );
139
140 start += length;
141 }
142
143 mexec.listen();
144 for (auto& x : runners) {
145 x.join();
146 }
147
148 for (const auto& err : errors) {
149 if (err) {
150 std::rethrow_exception(err);
151 }
152 }
153
154 return threads;
155}
156
157}
158
162#endif
167#endif
tatami bindings for arbitrary R matrices.
manticore::Executor & executor()
Definition parallelize.hpp:46
void set_executor(manticore::Executor *ptr)
Definition parallelize.hpp:65
int parallelize(const Function_ fun, const Index_ tasks, int threads)
Definition parallelize.hpp:97