Reputation: 118
I have a program that solves those two dimension mazes, it works quite fine to me, however I profiled it with gprof
(and @jrfonseca's fancy gprof2dot), it seemed to me it was taking a hard time with some operations and decided to do some parallelisation tries.
Basically in a function that consumed 50% (cpu?) time I had two choices of parallelising (multiple consumers for a single queue and parallel call of same function with similar not equal arguments) yet wanted to do both at first independently to check an initial assumption on which one would be better, I don't always do C++ code, and by searching the Internet on how to get std::thread
returning a value I read a nice answer with advices on std::future
, then I copied that to my code, so would you please know what this gets to mean...
bash-4.3$ sh build.sh
In file included from find_path.cpp:6:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/Xco
deDefault.xctoolchain/usr/bin/../include/c++/v1/future:371:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/thread:337:5: error:
attempt to use a deleted function
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_In...
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/thread:347:5:
in instantiation of function template specialization
'std::__1::__thread_execute<void
(*)(std::__1::priority_queue<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> &,
std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > &, std::__1::pair<int,
int> &, int, int, int, int, unsigned char *,
std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > &, int, int,
std::__1::promise<bool> &&),
std::__1::reference_wrapper<std::__1::priority_queue<std::__1::vector<std
::__1::pair<int,
int>, std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> >,
std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > >,
std::__1::reference_wrapper<std::__1::pair<int, int> >, int, int, int,
int, const unsigned char *,
std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > >, int, int,
std::__1::promise<bool> , 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12>'
requested here
__thread_execute(*__p, _Index());
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/thread:359:42: note:
in instantiation of function template specialization
'std::__1::__thread_proxy<std::__1::tuple<void
(*)(std::__1::priority_queue<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> &,
std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > &, std::__1::pair<int,
int> &, int, int, int, int, unsigned char *,
std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > &, int, int,
std::__1::promise<bool> &&),
std::__1::reference_wrapper<std::__1::priority_queue<std::__1::vector<std
::__1::pair<int,
int>, std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> >,
std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > >,
std::__1::reference_wrapper<std::__1::pair<int, int> >, int, int, int,
int, const unsigned char *,
std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > >, int, int,
std::__1::promise<bool> > >' requested here
int __ec = pthread_create(&__t_, 0, &__thread_proxy<_Gp>, __p.get());
^
find_path.cpp:258:25: note: in instantiation of function template specializatio
n
'std::__1::thread::thread<void
(*)(std::__1::priority_queue<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> &,
std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > &, std::__1::pair<int,
int> &, int, int, int, int, unsigned char *,
std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > &, int, int,
std::__1::promise<bool> &&),
std::__1::reference_wrapper<std::__1::priority_queue<std::__1::vector<std
::__1::pair<int,
int>, std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::vector<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > >,
std::__1::allocator<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > > >, NearerTarget> >,
std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > >,
std::__1::reference_wrapper<std::__1::pair<int, int> >, int &, int &,
const int &, const int &, const unsigned char *&,
std::__1::reference_wrapper<std::__1::vector<std::__1::pair<int, int>,
std::__1::allocator<std::__1::pair<int, int> > > >, const int &, int,
std::__1::promise<bool> , void>' requested here
std::thread n(&move, std::ref(active_paths),
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/../include/c++/v1/type_traits:1043:5: note:
'~__nat' has been explicitly marked deleted here
~__nat() = delete;
^
1 error generated.
bash-4.3$
... in this context?
Some find_path.cpp:
1 // For 'assert(expression)'.
2 #include <cassert>
3 // For 'std::abs' (absolute value function, integers version)'.
4 #include <cstdlib>
5 // For 'std::promise' and 'std::future'.
6 #include <future> // <--
7 // For 'std::mutex'.
8 #include <mutex>
9 // For 'std::priority_queue'.
10 #include <queue>
11 // For 'std::move'.
12 #include <utility>
13 // For 'std::vector'.
14 #include <vector>
15 // For 'std::thread'.
16 #include <thread>
17 // For 'std::get', 'std::make_tuple' and 'std::tuple'.
18 #include <tuple>
Some more:
242 // Do not add new paths unless deemed necessary.
243 bool add_north_move, add_west_move, add_south_move, add_east_move;
244 add_north_move = add_west_move = add_south_move = add_east_move =
245 0;
246
247 // Another helper.
248 std::vector < std::pair < int, int > > active_paths_top =
249 active_paths.top();
250 std::pair < int, int > active_paths_top_back =
251 active_paths_top.back();
252
253 // Directions clockwise (0: 'N', 1: 'E', 2: 'S', 3: 'W').
254 int direction = 0;
255
256 std::promise < bool > n_p;
257 auto n_f = n_p.get_future();
258 std::thread n(&move, std::ref(active_paths), // <--
259 std::ref(active_paths_top),
260 std::ref(active_paths_top_back), new_move_back_x, new_move_back_y,
261 nMapWidth, nMapHeight, pMap, std::ref(north_move), nOutBufferSize, direction++, std::move(n_p)
262 );
263 std::promise < bool > e_p;
264 auto e_f = e_p.get_future();
265 std::thread e(&move, std::ref(active_paths),
266 std::ref(active_paths_top),
267 std::ref(active_paths_top_back), new_move_back_x, new_move_back_y,
268 nMapWidth, nMapHeight, pMap, std::ref(east_move), nOutBufferSize, direction++, std::move(e_p)
269 );
Contents in void move(12)
:
108 void move(std::priority_queue <
109 std::vector < std::pair < int, int > >,
110 std::vector < std::vector < std::pair < int, int > > >,
111 NearerTarget
112 > & active_paths,
113 std::vector < std::pair < int, int > > & active_paths_top,
114 std::pair < int, int > & active_paths_top_back, int new_move_back_x, int new_move_back_y,
115 int map_width, int map_height, unsigned char * map, std::vector < std::pair < int, int > > & move,
116 int out_buffer_size, int direction,
117 std::promise < bool > && add_move) {
118 assert(-1 < direction && 4 > direction);
119 std::pair < int, int > new_coord;
120 switch (direction) {
121 case 0:
122 // Add move 'N'.
123 new_coord = std::make_pair(
124 active_paths_top_back.first,
125 active_paths_top_back.second + 1);
126 break;
127 case 1:
128 // Add move 'E'.
129 new_coord = std::make_pair(
130 active_paths_top_back.first + 1,
131 active_paths_top_back.second);
132 break;
133 case 2:
134 // Add move 'S'.
135 new_coord = std::make_pair(
136 active_paths_top_back.first,
137 active_paths_top_back.second - 1);
138 break;
139 case 3:
140 // Add move 'W'.
141 new_coord = std::make_pair(
142 active_paths_top_back.first - 1,
143 active_paths_top_back.second);
144 break;
145 }
146
147 // Push it to the queue of paths only if the movement
148 // makes sense.
149 new_move_back_x = new_coord.first;
150 new_move_back_y = new_coord.second;
151 if (new_move_back_x > -1 && new_move_back_x < map_width &&
152 new_move_back_y > -1 && new_move_back_y < map_height)
153 {
154 // Move is inside bounds.
155
156 // Check collision detection.
157 if (map[new_move_back_y * map_width + new_move_back_x])
158 {
159 // Check not visited.
160 if (! visited(
161 new_move_back_x,
162 new_move_back_y,
163 active_paths.top()))
164 {
165 move = active_paths_top;
166 move.reserve(out_buffer_size);
167 move.push_back(new_coord);
168 add_move.set_value(true);
169 }
170 }
171 }
172 }
It tells I explicited marked deleted ~__nat
, I don't remember even dreaming on doing such a thing.
Am somewhat used to pthreads, Python threads, the Java parallel model... not much versed on indeterminate selections, async in general, promises... Should I yield efforts leaving std::future
use?
Upvotes: 0
Views: 1489
Reputation: 51
The error message relates to a new C++ feature, 'deleting' default operators to make them inaccessible (before, the usual technique was to make them private).
In your case, it indicates an issue with the arguments to the thread constructor. Your code is quite complex, but you might have run into this issue: C++ std::thread "Attempt to use a deleted function"
I would certainly recommend to continue with std:future. For an introduction, the following talk by Herb Sutter on the new C++ concurrency features is highly recommended: https://channel9.msdn.com/Shows/Going+Deep/C-and-Beyond-2012-Herb-Sutter-Concurrency-and-Parallelism
Upvotes: 2