1 | /* |
2 | * map_vector.hpp |
3 | * |
4 | * Created on: Aug 30, 2014 |
5 | * Author: Pietro Incardona |
6 | */ |
7 | |
8 | #ifndef MAP_VECTOR_HPP |
9 | #define MAP_VECTOR_HPP |
10 | |
11 | #include "util/cuda_launch.hpp" |
12 | #include <iostream> |
13 | #include <typeinfo> |
14 | #include "util/common.hpp" |
15 | #include "memory/PtrMemory.hpp" |
16 | #include "util/object_util.hpp" |
17 | #include "Grid/util.hpp" |
18 | #include "Vector/util.hpp" |
19 | #include "Vector/map_vector_grow_p.hpp" |
20 | #include "memory/ExtPreAlloc.hpp" |
21 | #include "util/util_debug.hpp" |
22 | #include "util/Pack_stat.hpp" |
23 | #include "Grid/map_grid.hpp" |
24 | #include "memory/HeapMemory.hpp" |
25 | #include "vect_isel.hpp" |
26 | #include "util/object_s_di.hpp" |
27 | #include "util.hpp" |
28 | #include "util/Pack_stat.hpp" |
29 | #include "memory/ExtPreAlloc.hpp" |
30 | #include <string.h> |
31 | #include "Packer_Unpacker/Unpacker.hpp" |
32 | #include "Packer_Unpacker/Packer.hpp" |
33 | #include <fstream> |
34 | #include "Packer_Unpacker/Packer_util.hpp" |
35 | #include "Packer_Unpacker/has_pack_agg.hpp" |
36 | #include "timer.hpp" |
37 | #include "map_vector_std_util.hpp" |
38 | #include "data_type/aggregate.hpp" |
39 | #include "vector_map_iterator.hpp" |
40 | #include "util/cuda_util.hpp" |
41 | #include "cuda/map_vector_cuda_ker.cuh" |
42 | #include "map_vector_printers.hpp" |
43 | |
44 | namespace openfpm |
45 | { |
46 | |
47 | template<bool is_ok_cuda,typename T, typename Memory, |
48 | template<typename> class layout_base, |
49 | typename grow_p> |
50 | struct add_prp_device_impl |
51 | { |
52 | template <typename S, |
53 | typename M, |
54 | typename gp, |
55 | unsigned int impl, |
56 | template <typename> class layout_base2, |
57 | unsigned int ...args> |
58 | static void run(openfpm::vector<T,Memory,layout_base,grow_p,impl> & this_ ,const openfpm::vector<S,M,layout_base2,gp,impl> & v) |
59 | { |
60 | std::cout << __FILE__ << ":" << __LINE__ << " Error the function add_prp_device only work with cuda enabled vector" << std::endl; |
61 | } |
62 | }; |
63 | |
64 | template<bool is_ok_cuda,typename T, typename Memory, |
65 | template<typename> class layout_base, |
66 | typename grow_p> |
67 | struct merge_prp_device_impl |
68 | { |
69 | template <typename S, |
70 | typename M, |
71 | typename gp, |
72 | unsigned int impl, |
73 | template <typename> class layout_base2, |
74 | unsigned int ...args> |
75 | static void run(openfpm::vector<T,Memory,layout_base,grow_p,impl> & this_ , |
76 | const openfpm::vector<S,M,layout_base2,gp,impl> & v, |
77 | unsigned int offset) |
78 | { |
79 | std::cout << __FILE__ << ":" << __LINE__ << " Error the function merge_prp_device only work with cuda enabled vector" << std::endl; |
80 | } |
81 | }; |
82 | |
83 | template<typename T, typename Memory, |
84 | template<typename> class layout_base, |
85 | typename grow_p> |
86 | struct add_prp_device_impl<true,T,Memory,layout_base,grow_p> |
87 | { |
88 | template <typename S, |
89 | typename M, |
90 | typename gp, |
91 | unsigned int impl, |
92 | template <typename> class layout_base2, |
93 | unsigned int ...args> |
94 | static void run(vector<T,Memory,layout_base,grow_p,impl> & this_ ,const vector<S,M,layout_base2,gp,impl> & v) |
95 | { |
96 | // merge the data on device |
97 | |
98 | #if defined(CUDA_GPU) && defined(__NVCC__) |
99 | |
100 | size_t old_sz = this_.size(); |
101 | this_.resize(this_.size() + v.size(),DATA_ON_DEVICE); |
102 | |
103 | auto ite = v.getGPUIterator(); |
104 | |
105 | CUDA_LAUNCH((merge_add_prp_device_impl<decltype(v.toKernel()),decltype(this_.toKernel()),args...>),ite,v.toKernel(),this_.toKernel(),(unsigned int)old_sz); |
106 | |
107 | #else |
108 | std::cout << __FILE__ << ":" << __LINE__ << " Error the function add_prp_device only work when map_vector is compiled with nvcc" << std::endl; |
109 | #endif |
110 | } |
111 | }; |
112 | |
113 | template<typename T, typename Memory, |
114 | template<typename> class layout_base, |
115 | typename grow_p> |
116 | struct merge_prp_device_impl<true,T,Memory,layout_base,grow_p> |
117 | { |
118 | template <typename S, |
119 | typename M, |
120 | typename gp, |
121 | unsigned int impl, |
122 | template <typename> class layout_base2, |
123 | unsigned int ...args> |
124 | static void run(vector<T,Memory,layout_base,grow_p,impl> & this_ , |
125 | const vector<S,M,layout_base2,gp,impl> & v, |
126 | unsigned int offset) |
127 | { |
128 | // merge the data on device |
129 | |
130 | #if defined(CUDA_GPU) && defined(__NVCC__) |
131 | |
132 | auto ite = v.getGPUIterator(); |
133 | |
134 | CUDA_LAUNCH((merge_add_prp_device_impl<decltype(v.toKernel()),decltype(this_.toKernel()),args...>),ite,v.toKernel(),this_.toKernel(),(unsigned int)offset); |
135 | |
136 | #else |
137 | std::cout << __FILE__ << ":" << __LINE__ << " Error the function merge_prp_device only work when map_vector is compiled with nvcc" << std::endl; |
138 | #endif |
139 | } |
140 | }; |
141 | |
142 | |
143 | /*! \brief Implementation of 1-D std::vector like structure |
144 | * |
145 | * Stub object look at the various implementations |
146 | * |
147 | * \tparam T type of object the vector store |
148 | * \tparam Memory allocator to use |
149 | * \tparam layout layout to use |
150 | * \tparam grow_p grow policy for vector in case of reallocation |
151 | * |
152 | * \see vector<T,HeapMemory,grow_policy_double,STD_VECTOR> |
153 | * \see vector<T,Memory,grow_p,OPENFPM_NATIVE> |
154 | * \see vector<T,Memory,grow_p,OPENFPM_NATIVE> |
155 | * |
156 | */ |
157 | template<typename T, typename Memory, template<typename> class layout_base, typename grow_p, unsigned int impl> |
158 | class vector |
159 | { |
160 | /*! \brief Stub size |
161 | * |
162 | * Report an error |
163 | * |
164 | * \return 0 |
165 | * |
166 | */ |
167 | size_t size() |
168 | { |
169 | std::cerr << __FILE__ << ":" << __LINE__ << " Error stub vector created" << std::endl; |
170 | return 0; |
171 | } |
172 | }; |
173 | |
174 | #include "map_vector_std.hpp" |
175 | #include "map_vector_std_ptr.hpp" |
176 | |
177 | #ifdef CUDA_GPU |
178 | #include "cuda/map_vector_std_cuda.hpp" |
179 | #endif |
180 | |
181 | /*! \brief Implementation of 1-D std::vector like structure |
182 | * |
183 | * The layout is memory_traits_lin |
184 | * |
185 | * ### Add and access elements |
186 | * \snippet vector_test_util.hpp Create add and access |
187 | * |
188 | * \tparam T type of object the vector store |
189 | * \tparam Memory allocator to use |
190 | * \tparam layout layout to use |
191 | * \tparam grow_p grow policy for vector in case of reallocation |
192 | * |
193 | * OPENFPM_NATIVE implementation |
194 | * |
195 | */ |
196 | template<typename T,typename Memory, template <typename> class layout_base, typename grow_p> |
197 | class vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> |
198 | { |
199 | typedef vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> self_type; |
200 | |
201 | //! Actual size of the vector, warning: it is not the space allocated in grid |
202 | //! grid size increase by a fixed amount every time we need a vector bigger than |
203 | //! the actually allocated space |
204 | size_t v_size; |
205 | |
206 | //! 1-D static grid |
207 | grid_base<1,T,Memory,typename layout_base<T>::type> base; |
208 | |
209 | /*! \brief If the argument is zero return 1 otherwise return the argument |
210 | * |
211 | * \param sz output |
212 | * \param arg argument |
213 | * |
214 | */ |
215 | void non_zero_one(size_t sz[1], size_t arg) |
216 | { |
217 | if (arg == 0) |
218 | {sz[0] = 1;} |
219 | else |
220 | {sz[0] = arg;} |
221 | } |
222 | |
223 | #ifdef SE_CLASS1 |
224 | |
225 | /*! \brief Check that id is not bigger than the vector size |
226 | * |
227 | * \param id element id |
228 | * |
229 | */ |
230 | |
231 | void check_overflow(size_t id) const |
232 | { |
233 | if (id >= v_size) |
234 | { |
235 | std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " overflow id: " << id << "\n" ; |
236 | ACTION_ON_ERROR(VECTOR_ERROR_OBJECT); |
237 | } |
238 | } |
239 | |
240 | #endif |
241 | |
242 | public: |
243 | |
244 | //! it define that it is a vector |
245 | typedef int yes_i_am_vector; |
246 | |
247 | //! it define that it is a vector |
248 | typedef int yes_i_am_vector_native; |
249 | |
250 | //! Type of the encapsulation memory parameter |
251 | typedef typename layout_base<T>::type layout_type; |
252 | |
253 | //! Type of the encapsulation memory parameter |
254 | typedef layout_base<T> layout_base_; |
255 | |
256 | //! iterator for the vector |
257 | typedef vector_key_iterator iterator_key; |
258 | |
259 | //! Object container for T, it is the return type of get_o it return a object type trough |
260 | // you can access all the properties of T |
261 | typedef typename grid_base<1,T,Memory,typename layout_base<T>::type>::container container; |
262 | |
263 | //! Type of the value the vector is storing |
264 | typedef T value_type; |
265 | |
266 | //! Type of memory this vector use |
267 | typedef Memory Memory_type; |
268 | |
269 | //! growing policy of this vector |
270 | typedef grow_p grow_policy; |
271 | |
272 | template<typename Tobj> |
273 | struct layout_base__ |
274 | { |
275 | typedef layout_base<Tobj> type; |
276 | }; |
277 | |
278 | // Implementation of packer and unpacker for vector |
279 | #include "vector_pack_unpack.ipp" |
280 | |
281 | /*! \brief Return the size of the vector |
282 | * |
283 | * \return the size |
284 | * |
285 | */ |
286 | size_t size() const |
287 | { |
288 | return v_size; |
289 | } |
290 | |
291 | /*! \brief return the maximum capacity of the vector before reallocation |
292 | * |
293 | * \return the capacity of the vector |
294 | * |
295 | */ |
296 | |
297 | size_t capacity() |
298 | { |
299 | return base.size(); |
300 | } |
301 | |
302 | /*! \brief Reserve slots in the vector to avoid reallocation |
303 | * |
304 | * Reserve slots in the vector to avoid reallocation |
305 | * |
306 | * \param sp number of slot to reserve |
307 | * |
308 | */ |
309 | |
310 | void reserve(size_t sp) |
311 | { |
312 | if (sp > base.size()) |
313 | { |
314 | //! Resize the memory |
315 | size_t sz[1] = {sp}; |
316 | base.resize(sz); |
317 | } |
318 | } |
319 | |
320 | /*! \brief Clear the vector |
321 | * |
322 | * Eliminate all the elements for from the vector |
323 | * |
324 | */ |
325 | void clear() |
326 | { |
327 | resize(0); |
328 | } |
329 | |
330 | /*! \brief Clear the vector |
331 | * |
332 | * Eliminate all the elements for from the vector |
333 | * |
334 | */ |
335 | void shrink_to_fit() |
336 | { |
337 | size_t sz[1] = {size()}; |
338 | base.resize(sz); |
339 | } |
340 | |
341 | /*! \brief Resize the vector |
342 | * |
343 | * Resize the vector and allocate n elements |
344 | * |
345 | * \param opt options for resize. In case we know that the data are only on device memory we can use DATA_ONLY_DEVICE, |
346 | * In case we know that the data are only on host memory we can use DATA_ONLY_HOST |
347 | * |
348 | * \param blockSize The default is equal to 1. In case of accelerator buffer resize indicate the size of the block of |
349 | * threads ( this is used in case of a vector of blocks where the block object override to operator= |
350 | * to distribute threads on each block element ) |
351 | * |
352 | */ |
353 | void resize(size_t slot, size_t opt = DATA_ON_DEVICE | DATA_ON_HOST, unsigned int blockSize = 1) |
354 | { |
355 | // If we need more space than what we allocated, allocate new memory |
356 | |
357 | if (slot > base.size()) |
358 | { |
359 | size_t gr = slot; |
360 | // If you increase by one we smartly resize the internal capacity more than 1 |
361 | // This is to make faster patterns like resize(size()+1) |
362 | if (slot - base.size() == 1 && opt && (opt & EXACT_RESIZE) == 0) |
363 | { |
364 | gr = grow_p::grow(base.size(),slot); |
365 | } |
366 | |
367 | //! Resize the memory |
368 | size_t sz[1] = {gr}; |
369 | |
370 | base.resize(sz,opt,blockSize); |
371 | } |
372 | |
373 | // update the vector size |
374 | v_size = slot; |
375 | } |
376 | |
377 | |
378 | /*! \brief Resize the vector () |
379 | * |
380 | * Resize the vector and allocate n elements |
381 | * |
382 | * \param slot number of elements |
383 | * \param opt options |
384 | * |
385 | */ |
386 | void resize_no_device(size_t slot) |
387 | { |
388 | // If we need more space than what we allocated, allocate new memory |
389 | |
390 | if (slot > base.size()) |
391 | { |
392 | size_t gr = grow_p::grow(base.size(),slot); |
393 | |
394 | //! Resize the memory |
395 | size_t sz[1] = {gr}; |
396 | base.resize_no_device(sz); |
397 | } |
398 | |
399 | // update the vector size |
400 | v_size = slot; |
401 | } |
402 | |
403 | //! Access key for the vector |
404 | typedef size_t access_key; |
405 | |
406 | /*! \brief It insert a new emtpy object on the vector, eventually it reallocate the grid |
407 | * |
408 | * \warning It is not thread safe should not be used in multi-thread environment |
409 | * reallocation, work only on cpu |
410 | * |
411 | */ |
412 | void add() |
413 | { |
414 | //! Check if we have enough space |
415 | |
416 | if (v_size >= base.size()) |
417 | { |
418 | //! Resize the memory, double up the actual memory allocated for the vector |
419 | size_t sz[1]; |
420 | non_zero_one(sz,2*base.size()); |
421 | base.resize(sz); |
422 | } |
423 | |
424 | //! increase the vector size |
425 | v_size++; |
426 | } |
427 | |
428 | /*! \brief It insert a new emtpy object on the vector, eventually it reallocate the grid |
429 | * |
430 | * \warning It is not thread safe should not be used in multi-thread environment |
431 | * reallocation, work only on cpu |
432 | * |
433 | */ |
434 | void add_no_device() |
435 | { |
436 | //! Check if we have enough space |
437 | |
438 | if (v_size >= base.size()) |
439 | { |
440 | //! Resize the memory, double up the actual memory allocated for the vector |
441 | size_t sz[1]; |
442 | non_zero_one(sz,2*base.size()); |
443 | base.resize_no_device(sz); |
444 | } |
445 | |
446 | //! increase the vector size |
447 | v_size++; |
448 | } |
449 | |
450 | /*! \brief It insert a new object on the vector, eventually it reallocate the grid |
451 | * |
452 | * \param v element to add |
453 | * |
454 | * \warning It is not thread safe should not be used in multi-thread environment |
455 | * reallocation, work only on cpu |
456 | * |
457 | */ |
458 | void add(const T & v) |
459 | { |
460 | //! Check if we have enough space |
461 | |
462 | if (v_size >= base.size()) |
463 | { |
464 | //! Resize the memory, double up the actual memory allocated for the vector |
465 | size_t sz[1]; |
466 | non_zero_one(sz,2*base.size()); |
467 | base.resize(sz); |
468 | } |
469 | |
470 | //! copy the element |
471 | base.set(v_size,v); |
472 | |
473 | //! increase the vector size |
474 | v_size++; |
475 | } |
476 | |
477 | /*! \brief It insert a new object on the vector, eventually it reallocate the vector |
478 | * |
479 | * \param v object (encapsulated) |
480 | * |
481 | * \warning It is not thread safe should not be used in multi-thread environment |
482 | * reallocation, work only on cpu |
483 | * |
484 | * |
485 | */ |
486 | void add(const typename grid_base<1,T,Memory,typename layout_base<T>::type>::container & v) |
487 | { |
488 | //! Check if we have enough space |
489 | |
490 | if (v_size >= base.size()) |
491 | { |
492 | //! Resize the memory, double up the actual memory allocated for the vector |
493 | size_t sz[1]; |
494 | non_zero_one(sz,2*base.size()); |
495 | base.resize(sz); |
496 | } |
497 | |
498 | //! copy the added element |
499 | base.set(v_size,v); |
500 | |
501 | //! increase the vector size |
502 | v_size++; |
503 | } |
504 | |
505 | /*! \brief It add the element of another vector to this vector |
506 | * |
507 | * \param v from where to take the vector |
508 | * |
509 | */ |
510 | template <typename M, typename gp> void add(const vector<T, M, layout_base,gp,OPENFPM_NATIVE> & v) |
511 | { |
512 | //! Add the element of v |
513 | for (size_t i = 0 ; i < v.size() ; i++) |
514 | add(v.get(i)); |
515 | } |
516 | |
517 | /*! \brief It merge the elements of a source vector to this vector |
518 | * |
519 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
520 | * Merging the second vector v2 to |
521 | * the first one v1 starting from the element 2. Mean |
522 | * |
523 | * \verbatim |
524 | * |
525 | * 6 8 3 2 1 0 3 v1 elements |
526 | * | | | |
527 | * op op op |
528 | * | | | |
529 | * 5 1 9 v2 elements |
530 | * |
531 | *------------------------------------- |
532 | * 6 8 8 3 10 0 3 updated v1 elements |
533 | * |
534 | * This operation is done for each selected property in args |
535 | * |
536 | * \endverbatim |
537 | * |
538 | * The number of properties in the source vector must be smaller than the destination |
539 | * all the properties of S must be mapped so if S has 3 properties |
540 | * 3 numbers for args are required |
541 | * |
542 | * \tparam op merging operation |
543 | * \tparam S Base object of the source vector |
544 | * \tparam M memory type of the source vector |
545 | * \tparam gp Grow policy of the source vector |
546 | * \tparam args one or more number that define which property to set-up |
547 | * |
548 | * \param v source vector |
549 | * \param start index from where to start the merging |
550 | * |
551 | */ |
552 | template <template<typename,typename> class op, typename S, typename M, typename gp, unsigned int ...args> |
553 | void merge_prp(const vector<S,M,layout_base,gp,OPENFPM_NATIVE> & v, |
554 | const openfpm::vector<size_t> & opart) |
555 | { |
556 | #ifdef SE_CLASS1 |
557 | |
558 | if (v.size() != opart.size()) |
559 | std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be the same as o_part.size()" << opart.size() << std::endl; |
560 | |
561 | #endif |
562 | //! Add the element of v |
563 | for (size_t i = 0 ; i < v.size() ; i++) |
564 | { |
565 | #ifdef SE_CLASS1 |
566 | |
567 | if (opart.get(i) > size()) |
568 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " try to access element " << opart.get(i) << " but the vector has size " << size() << std::endl; |
569 | |
570 | #endif |
571 | // write the object in the last element |
572 | object_s_di_op<op,decltype(v.get(i)),decltype(get(size()-1)),OBJ_ENCAP,args...>(v.get(i),get(opart.get(i))); |
573 | } |
574 | } |
575 | |
576 | /*! \brief It merge the elements of a source vector to this vector (on device) |
577 | * |
578 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
579 | * Merging the second vector v2 to |
580 | * the first one v1 starting from the element 2. Mean |
581 | * |
582 | * \verbatim |
583 | * |
584 | * 6 8 3 2 1 0 3 v1 elements |
585 | * | | | |
586 | * op op op |
587 | * | | | |
588 | * 5 1 9 v2 elements |
589 | * |
590 | *------------------------------------- |
591 | * 6 8 8 3 10 0 3 updated v1 elements |
592 | * |
593 | * This operation is done for each selected property in args |
594 | * |
595 | * \endverbatim |
596 | * |
597 | * The number of properties in the source vector must be smaller than the destination |
598 | * all the properties of S must be mapped so if S has 3 properties |
599 | * 3 numbers for args are required |
600 | * |
601 | * \tparam op merging operation |
602 | * \tparam S Base object of the source vector |
603 | * \tparam M memory type of the source vector |
604 | * \tparam gp Grow policy of the source vector |
605 | * \tparam args one or more number that define which property to set-up |
606 | * |
607 | * \param v source vector |
608 | * \param start index from where to start the merging |
609 | * |
610 | */ |
611 | template <template<typename,typename> class op, typename S, typename M, typename gp, unsigned int ...args> |
612 | void merge_prp_device(const vector<S,M,layout_base,gp,OPENFPM_NATIVE> & v, |
613 | unsigned int start) |
614 | { |
615 | merge_prp_device_impl<std::is_same<Memory,CudaMemory>::value,T,Memory,layout_base,grow_p> |
616 | ::template run<S,M,gp,OPENFPM_NATIVE,layout_base,args...>(*this,v,start); |
617 | } |
618 | |
619 | |
620 | /*! \brief It merge the elements of a source vector to this vector |
621 | * |
622 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
623 | * Merging the second vector v2 to |
624 | * the first one v1 starting from the element 2. Mean |
625 | * |
626 | * \verbarim |
627 | * |
628 | * 6 8 3 2 1 0 3 v1 elements |
629 | * | | | |
630 | * op op op |
631 | * | | | |
632 | * 5 1 9 v2 elements |
633 | * |
634 | *------------------------------------- |
635 | * 6 8 8 3 10 0 3 updated v1 elements |
636 | * |
637 | * This operation is done for each selected property in args |
638 | * |
639 | * \endverbatim |
640 | * |
641 | * The number of properties in the source vector must be smaller than the destination |
642 | * all the properties of S must be mapped so if S has 3 properties |
643 | * 3 numbers for args are required |
644 | * |
645 | * \tparam op merging operation |
646 | * \tparam S Base object of the source vector |
647 | * \tparam M memory type of the source vector |
648 | * \tparam gp Grow policy of the source vector |
649 | * \tparam args one or more number that define which property to set-up |
650 | * |
651 | * \param v source vector |
652 | * \param start index from where to start the merging |
653 | * |
654 | */ |
655 | template <template<typename,typename> class op, |
656 | typename S, |
657 | typename M, |
658 | typename gp, |
659 | template <typename> class layout_base2, |
660 | typename vector_opart_type, |
661 | unsigned int ...args> |
662 | void merge_prp_v(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v, |
663 | const vector_opart_type & opart) |
664 | { |
665 | #ifdef SE_CLASS1 |
666 | |
667 | if (v.size() != opart.size()) |
668 | std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be the same as o_part.size()" << opart.size() << std::endl; |
669 | |
670 | #endif |
671 | //! Add the element of v |
672 | for (size_t i = 0 ; i < v.size() ; i++) |
673 | { |
674 | #ifdef SE_CLASS1 |
675 | |
676 | if (i >= opart.size()) |
677 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " try to access element " << opart.template get<0>(i) << " but the vector has size " << size() << std::endl; |
678 | |
679 | #endif |
680 | // write the object in the last element |
681 | object_s_di_op<op,decltype(v.get(i)),decltype(get(size()-1)),OBJ_ENCAP,args...>(v.get(i),get(opart.template get<0>(i))); |
682 | } |
683 | } |
684 | |
685 | /*! \brief It merge the elements of a source vector to this vector |
686 | * |
687 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
688 | * Merging the second vector v2 to |
689 | * the first one v1 starting from the element 2. Mean |
690 | * |
691 | * \verbarim |
692 | * |
693 | * 6 8 3 2 1 0 3 v1 elements |
694 | * | | | |
695 | * op op op |
696 | * | | | |
697 | * 5 1 9 v2 elements |
698 | * |
699 | *------------------------------------- |
700 | * 6 8 8 3 10 0 3 updated v1 elements |
701 | * |
702 | * This operation is done for each selected property in args |
703 | * |
704 | * \endverbatim |
705 | * |
706 | * The number of properties in the source vector must be smaller than the destination |
707 | * all the properties of S must be mapped so if S has 3 properties |
708 | * 3 numbers for args are required |
709 | * |
710 | * \tparam op merging operation |
711 | * \tparam S Base object of the source vector |
712 | * \tparam M memory type of the source vector |
713 | * \tparam gp Grow policy of the source vector |
714 | * \tparam args one or more number that define which property to set-up |
715 | * |
716 | * \param v source vector |
717 | * \param offset offset from where to copy in v |
718 | * \param start index from where to start the merging |
719 | * |
720 | */ |
721 | template <template<typename,typename> class op, |
722 | typename S, |
723 | typename M, |
724 | typename gp, |
725 | template <typename> class layout_base2, |
726 | typename vector_opart_type, |
727 | unsigned int ...args> |
728 | void merge_prp_v(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v, |
729 | unsigned int offset, |
730 | const vector_opart_type & opart) |
731 | { |
732 | size_t i2 = 0; |
733 | |
734 | for (size_t i = offset ; i < v.size() ; i++) |
735 | { |
736 | auto dst = v.get(opart.template get<0>(i2)); |
737 | auto src = v.get(i); |
738 | copy_cpu_encap_encap_op_prp<op,decltype(v.get(0)),decltype(v.get(0)),args...> cp(src,dst); |
739 | |
740 | boost::mpl::for_each_ref< boost::mpl::range_c<int,0,sizeof...(args)> >(cp); |
741 | i2++; |
742 | } |
743 | } |
744 | |
745 | /*! \brief It merge the elements of a source vector to this vector |
746 | * |
747 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
748 | * Merging the second vector v2 to |
749 | * the first one v1 starting from the element 2. Mean |
750 | * |
751 | * \verbarim |
752 | * |
753 | * 6 8 3 2 1 0 3 v1 elements |
754 | * | | | |
755 | * op op op |
756 | * | | | |
757 | * 5 1 9 v2 elements |
758 | * |
759 | *------------------------------------- |
760 | * 6 8 8 3 10 0 3 updated v1 elements |
761 | * |
762 | * This operation is done for each selected property in args |
763 | * |
764 | * \endverbatim |
765 | * |
766 | * The number of properties in the source vector must be smaller than the destination |
767 | * all the properties of S must be mapped so if S has 3 properties |
768 | * 3 numbers for args are required |
769 | * |
770 | * \tparam op merging operation |
771 | * \tparam S Base object of the source vector |
772 | * \tparam M memory type of the source vector |
773 | * \tparam gp Grow policy of the source vector |
774 | * \tparam args one or more number that define which property to set-up |
775 | * |
776 | * \param v source vector |
777 | * \param opart merging indexes (property 1) |
778 | * \param start starting merging index for opart |
779 | * \param stop stop merging index for opart |
780 | * |
781 | */ |
782 | template <template<typename,typename> class op, |
783 | typename S, |
784 | typename M, |
785 | typename gp, |
786 | template <typename> class layout_base2, |
787 | typename vector_opart_type, |
788 | unsigned int ...args> |
789 | void merge_prp_v_device(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v, |
790 | const vector_opart_type & opart, |
791 | unsigned int start, |
792 | unsigned int stop) |
793 | { |
794 | #ifdef SE_CLASS1 |
795 | |
796 | if (v.size() != stop - start) |
797 | std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be the same as stop - start" << stop - start << std::endl; |
798 | |
799 | #endif |
800 | |
801 | #ifdef __NVCC__ |
802 | |
803 | size_t sz[1] = {stop - start}; |
804 | grid_sm<1,void> nm(sz); |
805 | |
806 | auto ite = nm.getGPUIterator(); |
807 | |
808 | // write the object in the last element |
809 | CUDA_LAUNCH((merge_add_prp_device_impl_src_dst_opar_offset<op, |
810 | decltype(v.toKernel()), |
811 | decltype(this->toKernel()), |
812 | decltype(opart.toKernel()), |
813 | args...>),ite,v.toKernel(),this->toKernel(),opart.toKernel(),start); |
814 | |
815 | // calculate |
816 | #else |
817 | std::cout << __FILE__ << ":" << __LINE__ << " Error you have to compile map_vector.hpp with nvcc to make GPU code working" << std::endl; |
818 | |
819 | #endif |
820 | } |
821 | |
822 | /*! \brief It merge the elements of a source vector to this vector |
823 | * |
824 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
825 | * Merging the second vector v2 to |
826 | * the first one v1 starting from the element 2. Mean |
827 | * |
828 | * \verbarim |
829 | * |
830 | * 6 8 3 2 1 0 3 v1 elements |
831 | * | | | |
832 | * op op op |
833 | * | | | |
834 | * 5 1 9 v2 elements |
835 | * |
836 | *------------------------------------- |
837 | * 6 8 8 3 10 0 3 updated v1 elements |
838 | * |
839 | * This operation is done for each selected property in args |
840 | * |
841 | * \endverbatim |
842 | * |
843 | * The number of properties in the source vector must be smaller than the destination |
844 | * all the properties of S must be mapped so if S has 3 properties |
845 | * 3 numbers for args are required |
846 | * |
847 | * \tparam op merging operation |
848 | * \tparam S Base object of the source vector |
849 | * \tparam M memory type of the source vector |
850 | * \tparam gp Grow policy of the source vector |
851 | * \tparam args one or more number that define which property to set-up |
852 | * |
853 | * \param v source vector |
854 | * \param opart merging indexes (property 0) |
855 | * \param i starting mergong indexes |
856 | * |
857 | */ |
858 | template <template<typename,typename> class op, |
859 | typename S, |
860 | typename M, |
861 | typename gp, |
862 | template <typename> class layout_base2, |
863 | typename vector_opart_type, |
864 | unsigned int ...args> |
865 | void merge_prp_v_device(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v, |
866 | unsigned int start, |
867 | const vector_opart_type & opart) |
868 | { |
869 | #ifdef SE_CLASS1 |
870 | |
871 | if (v.size() < opart.size() + start) |
872 | std::cerr << __FILE__ << ":" << __LINE__ << " error merge_prp: v.size()=" << v.size() << " must be snaller than o_part.size() + start " << opart.size() + start << std::endl; |
873 | |
874 | #endif |
875 | |
876 | #ifdef __NVCC__ |
877 | |
878 | auto ite = opart.getGPUIterator(); |
879 | |
880 | // write the object in the last element |
881 | CUDA_LAUNCH((merge_add_prp_device_impl_src_offset_dst_opar<op, |
882 | decltype(v.toKernel()), |
883 | decltype(this->toKernel()), |
884 | decltype(opart.toKernel()), |
885 | args... >),ite,v.toKernel(),this->toKernel(),opart.toKernel(),start); |
886 | |
887 | // calculate |
888 | #else |
889 | std::cout << __FILE__ << ":" << __LINE__ << " Error you have to compile map_vector.hpp with nvcc to make GPU code working" << std::endl; |
890 | |
891 | #endif |
892 | } |
893 | |
894 | /*! \brief It merge the elements of a source vector to this vector |
895 | * |
896 | * Given 2 vector v1 and v2 of size 7,3. and as merging operation the function add. |
897 | * Merging the second vector v2 to |
898 | * the first one v1 starting from the element 2. Mean |
899 | * |
900 | * \verbarim |
901 | * |
902 | * 6 8 3 2 1 0 3 v1 elements |
903 | * | | | |
904 | * op op op |
905 | * | | | |
906 | * 5 1 9 v2 elements |
907 | * |
908 | *------------------------------------- |
909 | * 6 8 8 3 10 0 3 updated v1 elements |
910 | * |
911 | * This operation is done for each selected property in args |
912 | * |
913 | * \endverbatim |
914 | * |
915 | * The number of properties in the source vector must be smaller than the destination |
916 | * all the properties of S must be mapped so if S has 3 properties |
917 | * 3 numbers for args are required |
918 | * |
919 | * \tparam op merging operation |
920 | * \tparam S Base object of the source vector |
921 | * \tparam M memory type of the source vector |
922 | * \tparam gp Grow policy of the source vector |
923 | * \tparam args one or more number that define which property to set-up |
924 | * |
925 | * \param v source vector |
926 | * \param start index from where to start the merging |
927 | * |
928 | */ |
929 | template <template<typename,typename> class op, |
930 | typename S, |
931 | typename M, |
932 | typename gp, |
933 | template <typename> class layout_base2, |
934 | unsigned int ...args> |
935 | void merge_prp_v(const vector<S,M,layout_base2,gp,OPENFPM_NATIVE> & v, |
936 | size_t start) |
937 | { |
938 | //! Add the element of v |
939 | for (size_t i = 0 ; i < v.size() ; i++) |
940 | { |
941 | #ifdef SE_CLASS1 |
942 | |
943 | if (start + i >= v_size) |
944 | std::cerr << "Error: " << __FILE__ << ":" << __LINE__ << " try to access element " << start+i << " but the vector has size " << size() << std::endl; |
945 | |
946 | #endif |
947 | // write the object in the last element |
948 | object_s_di_op<op,decltype(v.get(0)),decltype(get(0)),OBJ_ENCAP,args...>(v.get(i),get(start+i)); |
949 | } |
950 | } |
951 | |
952 | /*! \brief It add the element of a source vector to this vector |
953 | * |
954 | * The number of properties in the source vector must be smaller than the destination |
955 | * all the properties of S must be mapped so if S has 3 properties |
956 | * 3 numbers for args are required |
957 | * |
958 | * \tparam S Base object of the source vector |
959 | * \tparam M memory type of the source vector |
960 | * \tparam gp Grow policy of the source vector |
961 | * \tparam args one or more number that define which property to set-up |
962 | * |
963 | * \param v source vector |
964 | * |
965 | */ |
966 | template <typename S, |
967 | typename M, |
968 | typename gp, |
969 | unsigned int impl, |
970 | template <typename> class layout_base2, |
971 | unsigned int ...args> |
972 | void add_prp(const vector<S,M,layout_base2,gp,impl> & v) |
973 | { |
974 | //! Add the element of v |
975 | for (size_t i = 0 ; i < v.size() ; i++) |
976 | { |
977 | // Add a new element |
978 | add(); |
979 | |
980 | // write the object in the last element |
981 | object_s_di<decltype(v.get(i)),decltype(get(size()-1)),OBJ_ENCAP,args...>(v.get(i),get(size()-1)); |
982 | } |
983 | } |
984 | |
985 | /*! \brief It add the element of a source vector to this vector |
986 | * |
987 | * The number of properties in the source vector must be smaller than the destination |
988 | * all the properties of S must be mapped so if S has 3 properties |
989 | * 3 numbers for args are required |
990 | * |
991 | * \tparam S Base object of the source vector |
992 | * \tparam M memory type of the source vector |
993 | * \tparam gp Grow policy of the source vector |
994 | * \tparam args one or more number that define which property to set-up |
995 | * |
996 | * \param v source vector |
997 | * |
998 | */ |
999 | template <typename S, |
1000 | typename M, |
1001 | typename gp, |
1002 | unsigned int impl, |
1003 | template <typename> class layout_base2, |
1004 | unsigned int ...args> |
1005 | void add_prp_device(const vector<S,M,layout_base2,gp,impl> & v) |
1006 | { |
1007 | add_prp_device_impl<std::is_same<Memory,CudaMemory>::value,T,Memory,layout_base,grow_p> |
1008 | ::template run<S,M,gp,impl,layout_base2,args...>(*this,v); |
1009 | } |
1010 | |
1011 | /*! \brief Insert an entry in the vector |
1012 | * |
1013 | * \size_t key Where to insert the element |
1014 | * |
1015 | */ |
1016 | void insert(size_t key) |
1017 | { |
1018 | add(); |
1019 | |
1020 | long int d_k = (long int)size()-1; |
1021 | long int s_k = (long int)size()-2; |
1022 | |
1023 | // keys |
1024 | while (s_k >= (long int)key) |
1025 | { |
1026 | set(d_k,get(s_k)); |
1027 | d_k--; |
1028 | s_k--; |
1029 | } |
1030 | } |
1031 | |
1032 | |
1033 | /*! \brief Remove one entry from the vector |
1034 | * |
1035 | * \param key element to remove |
1036 | * |
1037 | */ |
1038 | void remove(size_t key) |
1039 | { |
1040 | size_t d_k = key; |
1041 | size_t s_k = key + 1; |
1042 | |
1043 | // keys |
1044 | while (s_k < size()) |
1045 | { |
1046 | set(d_k,get(s_k)); |
1047 | d_k++; |
1048 | s_k++; |
1049 | } |
1050 | |
1051 | // re-calculate the vector size |
1052 | |
1053 | v_size--; |
1054 | } |
1055 | |
1056 | /*! \brief Remove several entries from the vector |
1057 | * |
1058 | * \warning the keys in the vector MUST be sorted |
1059 | * |
1060 | * \param keys objects id to remove |
1061 | * \param start key starting point |
1062 | * |
1063 | */ |
1064 | void remove(openfpm::vector<size_t> & keys, size_t start = 0) |
1065 | { |
1066 | // Nothing to remove return |
1067 | if (keys.size() <= start ) |
1068 | return; |
1069 | |
1070 | size_t a_key = start; |
1071 | size_t d_k = keys.get(a_key); |
1072 | size_t s_k = keys.get(a_key) + 1; |
1073 | |
1074 | // keys |
1075 | while (s_k < size()) |
1076 | { |
1077 | // s_k should always point to a key that is not going to be deleted |
1078 | while (a_key+1 < keys.size() && s_k == keys.get(a_key+1)) |
1079 | { |
1080 | a_key++; |
1081 | s_k = keys.get(a_key) + 1; |
1082 | } |
1083 | |
1084 | // In case of overflow |
1085 | if (s_k >= size()) |
1086 | break; |
1087 | |
1088 | set(d_k,get(s_k)); |
1089 | d_k++; |
1090 | s_k++; |
1091 | } |
1092 | |
1093 | // re-calculate the vector size |
1094 | |
1095 | v_size -= keys.size() - start; |
1096 | } |
1097 | |
1098 | /*! \brief Get an element of the vector |
1099 | * |
1100 | * Get an element of the vector |
1101 | * |
1102 | * \tparam p Property to get |
1103 | * \param id Element to get |
1104 | * |
1105 | * \return the element value requested |
1106 | * |
1107 | */ |
1108 | |
1109 | template <unsigned int p> |
1110 | inline auto get(size_t id) const -> decltype(base.template get<p>(grid_key_dx<1>(0))) |
1111 | { |
1112 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
1113 | check_overflow(id); |
1114 | #endif |
1115 | grid_key_dx<1> key(id); |
1116 | |
1117 | |
1118 | return base.template get<p>(key); |
1119 | } |
1120 | |
1121 | /*! \brief Get an element of the vector |
1122 | * |
1123 | * Get an element of the vector |
1124 | * |
1125 | * \param id Element to get |
1126 | * |
1127 | * \return the element (encapsulated) |
1128 | * |
1129 | */ |
1130 | inline auto get(size_t id) -> decltype(base.get_o(grid_key_dx<1>(id))) |
1131 | { |
1132 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
1133 | check_overflow(id); |
1134 | #endif |
1135 | grid_key_dx<1> key(id); |
1136 | |
1137 | return base.get_o(key); |
1138 | } |
1139 | |
1140 | /*! \brief Get an element of the vector |
1141 | * |
1142 | * Get an element of the vector |
1143 | * |
1144 | * \param id Element to get |
1145 | * |
1146 | * \return the element (encapsulated) |
1147 | * |
1148 | */ |
1149 | inline auto get(size_t id) const -> const decltype(base.get_o(grid_key_dx<1>(id))) |
1150 | { |
1151 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
1152 | check_overflow(id); |
1153 | #endif |
1154 | grid_key_dx<1> key(id); |
1155 | |
1156 | return base.get_o(key); |
1157 | } |
1158 | |
1159 | /*! \brief Get an element of the vector |
1160 | * |
1161 | * \deprecated |
1162 | * |
1163 | * exactly as get, exist to keep the compatibility with grid |
1164 | * |
1165 | * \param id Element to get |
1166 | * |
1167 | * \return the element (encapsulated) |
1168 | * |
1169 | */ |
1170 | |
1171 | inline const typename grid_base<1,T,Memory,typename layout_base<T>::type>::container get_o(size_t id) const |
1172 | { |
1173 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
1174 | check_overflow(id); |
1175 | #endif |
1176 | grid_key_dx<1> key(id); |
1177 | |
1178 | return base.get_o(key); |
1179 | } |
1180 | |
1181 | /*! \brief Fill the buffer with a byte |
1182 | * |
1183 | * \param c char to fill the buffer with |
1184 | * |
1185 | */ |
1186 | template<unsigned int id> void fill(unsigned char c) |
1187 | { |
1188 | base.template fill<id>(c); |
1189 | } |
1190 | |
1191 | /*! \brief It return the properties arrays. |
1192 | * |
1193 | * In case of Cuda memory it return the device pointers to pass to the kernels |
1194 | * |
1195 | * |
1196 | */ |
1197 | template<unsigned int id> void * getDeviceBufferCopy() |
1198 | { |
1199 | return base.template getDeviceBuffer<id>(); |
1200 | } |
1201 | |
1202 | /*! \brief It return the properties arrays. |
1203 | * |
1204 | * In case of Cuda memory it return the device pointers to pass to the kernels |
1205 | * |
1206 | * This variant does not copy the host memory to the device memory |
1207 | * |
1208 | * |
1209 | */ |
1210 | template<unsigned int id> void * getDeviceBuffer() |
1211 | { |
1212 | return base.template getDeviceBuffer<id>(); |
1213 | } |
1214 | |
1215 | |
1216 | /*! \brief Get the last element of the vector |
1217 | * |
1218 | * \return the last element (encapsulated) |
1219 | * |
1220 | */ |
1221 | inline const typename grid_base<1,T,Memory,layout_type>::container last() const |
1222 | { |
1223 | grid_key_dx<1> key(size()-1); |
1224 | |
1225 | return base.get_o(key); |
1226 | } |
1227 | |
1228 | /*! \brief Get an element of the vector |
1229 | * |
1230 | * Get an element of the vector |
1231 | * |
1232 | * \tparam p Property to get |
1233 | * \param id Element to get |
1234 | * |
1235 | * \return the element value requested |
1236 | * |
1237 | */ |
1238 | |
1239 | template <unsigned int p> |
1240 | inline auto get(size_t id) -> decltype(base.template get<p>(grid_key_dx<1>(0))) |
1241 | { |
1242 | #if defined(SE_CLASS1) && !defined(__NVCC__) |
1243 | check_overflow(id); |
1244 | #endif |
1245 | grid_key_dx<1> key(id); |
1246 | |
1247 | return base.template get<p>(key); |
1248 | } |
1249 | |
1250 | /*! \brief Get the last element of the vector |
1251 | * |
1252 | * \return the element (encapsulated) |
1253 | * |
1254 | */ |
1255 | |
1256 | inline typename grid_base<1,T,Memory,typename layout_base<T>::type >::container last() |
1257 | { |
1258 | grid_key_dx<1> key(size()-1); |
1259 | |
1260 | return base.get_o(key); |
1261 | } |
1262 | |
1263 | //! Destructor |
1264 | ~vector() THROW |
1265 | { |
1266 | // Eliminate the pointer |
1267 | } |
1268 | |
1269 | /*! \brief It duplicate the vector |
1270 | * |
1271 | * \return a duplicated vector |
1272 | * |
1273 | */ |
1274 | vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> duplicate() const |
1275 | { |
1276 | vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> dup; |
1277 | |
1278 | dup.v_size = v_size; |
1279 | dup.base.swap(base.duplicate()); |
1280 | |
1281 | // copy the device part |
1282 | // and device |
1283 | if (Memory::isDeviceHostSame() == false) |
1284 | { |
1285 | #ifdef __NVCC__ |
1286 | if (dup.size() != 0) |
1287 | { |
1288 | auto it = dup.getGPUIterator(); |
1289 | CUDA_LAUNCH(copy_two_vectors,it,dup.toKernel(),toKernel()); |
1290 | } |
1291 | #endif |
1292 | } |
1293 | |
1294 | return dup; |
1295 | } |
1296 | |
1297 | /*! \brief Constructor from another temporal vector |
1298 | * |
1299 | * \param v the vector |
1300 | * |
1301 | */ |
1302 | vector(vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> && v) |
1303 | :v_size(0) |
1304 | { |
1305 | swap(v); |
1306 | } |
1307 | |
1308 | /*! \brief Constructor from another constant vector |
1309 | * |
1310 | * \param v the vector |
1311 | * |
1312 | */ |
1313 | vector(const vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & v) THROW |
1314 | :v_size(0) |
1315 | { |
1316 | swap(v.duplicate()); |
1317 | } |
1318 | |
1319 | //! Constructor, vector of size 0 |
1320 | vector() THROW |
1321 | :v_size(0),base(0) |
1322 | { |
1323 | base.setMemory(); |
1324 | } |
1325 | |
1326 | //! Constructor, vector of size sz |
1327 | vector(size_t sz) THROW |
1328 | :v_size(sz),base(sz) |
1329 | { |
1330 | base.setMemory(); |
1331 | } |
1332 | |
1333 | /*! \brief Set the object id to obj |
1334 | * |
1335 | * \param id element |
1336 | * \param obj object (encapsulated) |
1337 | * |
1338 | */ |
1339 | void set(size_t id, const typename grid_base<1,T,Memory,typename layout_base<T>::type>::container & obj) |
1340 | { |
1341 | #ifdef SE_CLASS1 |
1342 | check_overflow(id); |
1343 | #endif |
1344 | //! copy the element |
1345 | base.set(id,obj); |
1346 | } |
1347 | |
1348 | /*! \brief It set an element of the vector from a object that is a subset of the vector properties |
1349 | * |
1350 | * The number of properties in the source vector must be smaller than the destination |
1351 | * all the properties of S must be mapped so if S has 3 properties |
1352 | * 3 numbers for args are required |
1353 | * |
1354 | * \tparam encap_S object that encapsulate the object |
1355 | * \tparam args ids of the properties to map the object to |
1356 | * |
1357 | * \param i element to set |
1358 | * \param obj object that encapsulate the object |
1359 | * |
1360 | * \param v source vector |
1361 | * |
1362 | */ |
1363 | template <typename encap_S, unsigned int ...args> void set_o(size_t i, const encap_S & obj) |
1364 | { |
1365 | // write the object in the last element |
1366 | object_s_di<encap_S,decltype(get(i)),OBJ_ENCAP,args...>(obj,get(i)); |
1367 | } |
1368 | |
1369 | /*! \brief Set the object id to obj |
1370 | * |
1371 | * \param id |
1372 | * \param obj |
1373 | * |
1374 | */ |
1375 | void set(size_t id, const T & obj) |
1376 | { |
1377 | #ifdef SE_CLASS1 |
1378 | check_overflow(id); |
1379 | #endif |
1380 | //! copy the element |
1381 | base.set(id,obj); |
1382 | } |
1383 | |
1384 | /*! \brief Set the element of the vector v from another element of another vector |
1385 | * |
1386 | * \param id element id |
1387 | * \param v vector source |
1388 | * \param src source element |
1389 | * |
1390 | */ |
1391 | void set(size_t id, vector<T,Memory,layout_base,grow_p,OPENFPM_NATIVE> & v, size_t src) |
1392 | { |
1393 | #ifdef SE_CLASS1 |
1394 | check_overflow(id); |
1395 | #endif |
1396 | base.set(id,v.base,src); |
1397 | } |
1398 | |
1399 | |
1400 | /*! \brief Assignment operator |
1401 | * |
1402 | * move semantic movement operator= |
1403 | * |
1404 | * \param mv vector |
1405 | * |
1406 | * \return itself |
1407 | * |
1408 | */ |
1409 | vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(vector<T, Memory, layout_base,grow_p,OPENFPM_NATIVE> && mv) |
1410 | { |
1411 | v_size = mv.v_size; |
1412 | base.swap(mv.base); |
1413 | |
1414 | return *this; |
1415 | } |
1416 | |
1417 | /*! \brief Assignment operator |
1418 | * |
1419 | * it copy |
1420 | * |
1421 | * \param mv vector |
1422 | * |
1423 | * \return itself |
1424 | * |
1425 | */ |
1426 | vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(const vector<T, Memory, layout_base ,grow_p,OPENFPM_NATIVE> & mv) |
1427 | { |
1428 | v_size = mv.v_size; |
1429 | size_t rsz[1] = {v_size}; |
1430 | base.resize(rsz); |
1431 | |
1432 | // copy the object on cpu |
1433 | for (size_t i = 0 ; i < v_size ; i++ ) |
1434 | { |
1435 | grid_key_dx<1> key(i); |
1436 | base.set(key,mv.base,key); |
1437 | } |
1438 | |
1439 | // and device |
1440 | if (Memory::isDeviceHostSame() == false) |
1441 | { |
1442 | #ifdef __NVCC__ |
1443 | if (mv.size() != 0) |
1444 | { |
1445 | auto it = mv.getGPUIterator(); |
1446 | CUDA_LAUNCH(copy_two_vectors,it,toKernel(),mv.toKernel()); |
1447 | } |
1448 | #endif |
1449 | } |
1450 | |
1451 | |
1452 | return *this; |
1453 | } |
1454 | |
1455 | /*! \brief Assignment operator |
1456 | * |
1457 | * move semantic movement operator= |
1458 | * |
1459 | * \param mv vector |
1460 | * |
1461 | * \return itself |
1462 | * |
1463 | */ |
1464 | template<typename Mem, typename gp> vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(vector<T, Mem, layout_base,gp,OPENFPM_NATIVE> && mv) |
1465 | { |
1466 | v_size = mv.v_size; |
1467 | base.swap(mv.base); |
1468 | |
1469 | return *this; |
1470 | } |
1471 | |
1472 | /*! \brief Assignment operator |
1473 | * |
1474 | * it copy |
1475 | * |
1476 | * \param mv vector |
1477 | * |
1478 | * \return itself |
1479 | * |
1480 | */ |
1481 | template<typename Mem, typename gp> vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & operator=(const vector<T, Mem, layout_base ,gp,OPENFPM_NATIVE> & mv) |
1482 | { |
1483 | v_size = mv.getInternal_v_size(); |
1484 | size_t rsz[1] = {v_size}; |
1485 | base.resize(rsz); |
1486 | |
1487 | // copy the object |
1488 | for (size_t i = 0 ; i < v_size ; i++ ) |
1489 | { |
1490 | grid_key_dx<1> key(i); |
1491 | base.set(key,mv.getInternal_base(),key); |
1492 | } |
1493 | |
1494 | // and device |
1495 | if (Memory::isDeviceHostSame() == false && Mem::isDeviceHostSame() == false) |
1496 | { |
1497 | #ifdef __NVCC__ |
1498 | if (mv.size() != 0) |
1499 | { |
1500 | auto it = mv.getGPUIterator(); |
1501 | CUDA_LAUNCH(copy_two_vectors,it,toKernel(),mv.toKernel()); |
1502 | } |
1503 | #endif |
1504 | } |
1505 | |
1506 | return *this; |
1507 | } |
1508 | |
1509 | /*! \brief Assignment operator |
1510 | * |
1511 | * move semantic movement operator= |
1512 | * |
1513 | * \param mv vector |
1514 | * |
1515 | * \return itself |
1516 | * |
1517 | */ |
1518 | template<typename Mem, template <typename> class layout_base2> |
1519 | vector<T, Memory,layout_base2,grow_p,OPENFPM_NATIVE> & operator=(vector<T, Mem, layout_base2,grow_p,OPENFPM_NATIVE> && mv) |
1520 | { |
1521 | v_size = mv.v_size; |
1522 | base.swap(mv.base); |
1523 | |
1524 | return *this; |
1525 | } |
1526 | |
1527 | /*! \brief Assignment operator |
1528 | * |
1529 | * |
1530 | * \param mv vector to copy |
1531 | * |
1532 | * \return itself |
1533 | * |
1534 | * |
1535 | */ |
1536 | template<typename Mem, |
1537 | template <typename> class layout_base2, |
1538 | typename check = typename std::enable_if<!std::is_same<typename layout_base2<T>::type,typename layout_base<T>::type>::value >::type> |
1539 | vector<T, Memory,layout_base,grow_p,OPENFPM_NATIVE> & |
1540 | operator=(const vector<T, Mem, layout_base2 ,grow_p,OPENFPM_NATIVE> & mv) |
1541 | { |
1542 | v_size = mv.getInternal_v_size(); |
1543 | size_t rsz[1] = {v_size}; |
1544 | base.resize(rsz); |
1545 | |
1546 | // copy the object |
1547 | for (size_t i = 0 ; i < v_size ; i++ ) |
1548 | { |
1549 | grid_key_dx<1> key(i); |
1550 | base.set_general(key,mv.getInternal_base(),key); |
1551 | } |
1552 | |
1553 | // and device |
1554 | if (Memory::isDeviceHostSame() == false && Mem::isDeviceHostSame() == false) |
1555 | { |
1556 | #ifdef __NVCC__ |
1557 | if (mv.size() != 0) |
1558 | { |
1559 | auto it = mv.getGPUIterator(); |
1560 | CUDA_LAUNCH(copy_two_vectors,it,toKernel(),mv.toKernel()); |
1561 | } |
1562 | #endif |
1563 | } |
1564 | |
1565 | return *this; |
1566 | } |
1567 | |
1568 | /*! \brief Check that two vectors are equal |
1569 | * |
1570 | * \param vector to compare |
1571 | * |
1572 | */ |
1573 | bool operator!=(const vector<T, Memory, layout_base,grow_p,OPENFPM_NATIVE> & v) const |
1574 | { |
1575 | return !this->operator==(v); |
1576 | } |
1577 | |
1578 | /*! \brief Check that two vectors are not equal |
1579 | * |
1580 | * \param vector to compare |
1581 | * |
1582 | */ |
1583 | bool operator==(const vector<T, Memory, layout_base, grow_p,OPENFPM_NATIVE> & v) const |
1584 | { |
1585 | if (v_size != v.v_size) |
1586 | return false; |
1587 | |
1588 | // check object by object |
1589 | for (size_t i = 0 ; i < v_size ; i++ ) |
1590 | { |
1591 | grid_key_dx<1> key(i); |
1592 | |
1593 | if (base.get_o(key) != v.base.get_o(key)) |
1594 | return false; |
1595 | } |
1596 | |
1597 | return true; |
1598 | } |
1599 | |
1600 | /*! \brief Swap the memory with another vector |
1601 | * |
1602 | * \note this is different from the normal swap please look a grid_base_implementation.hpp method swap_nomode |
1603 | * for info |
1604 | * |
1605 | * \param v vector |
1606 | * |
1607 | */ |
1608 | void swap_nomode(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> & v) |
1609 | { |
1610 | size_t sz_sp = v_size; |
1611 | |
1612 | // swap the v_size |
1613 | v_size = v.v_size; |
1614 | |
1615 | base.swap_nomode(v.base); |
1616 | v.v_size = sz_sp; |
1617 | } |
1618 | |
1619 | /*! \brief Swap the memory with another vector |
1620 | * |
1621 | * \param v vector |
1622 | * |
1623 | */ |
1624 | void swap(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> & v) |
1625 | { |
1626 | size_t sz_sp = v_size; |
1627 | |
1628 | // swap the v_size |
1629 | v_size = v.v_size; |
1630 | |
1631 | base.swap(v.base); |
1632 | v.v_size = sz_sp; |
1633 | } |
1634 | |
1635 | /*! \brief Swap the memory with another vector |
1636 | * |
1637 | * \param v vector |
1638 | * |
1639 | */ |
1640 | void swap(openfpm::vector<T,Memory, layout_base,grow_p,OPENFPM_NATIVE> && v) |
1641 | { |
1642 | size_t sz_sp = v_size; |
1643 | |
1644 | // swap the v_size |
1645 | v_size = v.v_size; |
1646 | |
1647 | base.swap(v.base); |
1648 | v.v_size = sz_sp; |
1649 | } |
1650 | |
1651 | /*! \brief Get iterator over the particles from a particular index |
1652 | * |
1653 | * \param start starting point |
1654 | * |
1655 | * \return an iterator to iterate from a particular index |
1656 | * |
1657 | */ |
1658 | vector_key_iterator getIteratorFrom(size_t start) const |
1659 | { |
1660 | return vector_key_iterator(v_size,start); |
1661 | } |
1662 | |
1663 | /*! \brief Get iterator over the particles from 0 until a particular index |
1664 | * |
1665 | * \warning stop point is not included |
1666 | * |
1667 | * \param stop stop point |
1668 | * |
1669 | * \return an iterator to iterate until a particular index |
1670 | * |
1671 | */ |
1672 | vector_key_iterator getIteratorTo(size_t stop) const |
1673 | { |
1674 | return vector_key_iterator(stop,0); |
1675 | } |
1676 | |
1677 | #ifdef CUDA_GPU |
1678 | |
1679 | /*! \brief Get an iterator for the GPU |
1680 | * |
1681 | * |
1682 | */ |
1683 | ite_gpu<1> getGPUIteratorTo(long int stop, size_t n_thr = 1024) const |
1684 | { |
1685 | grid_key_dx<1,long int> start(0); |
1686 | grid_key_dx<1,long int> stop_(stop); |
1687 | |
1688 | return base.getGPUIterator(start,stop_,n_thr); |
1689 | } |
1690 | |
1691 | #endif |
1692 | |
1693 | /*! \brief Get the vector elements iterator |
1694 | * |
1695 | * |
1696 | * \return an iterator to iterate through all the elements of the vector |
1697 | * |
1698 | */ |
1699 | |
1700 | vector_key_iterator getIterator() const |
1701 | { |
1702 | return vector_key_iterator(v_size); |
1703 | } |
1704 | |
1705 | #ifdef CUDA_GPU |
1706 | |
1707 | /*! \brief Get an iterator for the GPU |
1708 | * |
1709 | * |
1710 | */ |
1711 | ite_gpu<1> getGPUIterator(size_t n_thr = 1024) const |
1712 | { |
1713 | grid_key_dx<1> start(0); |
1714 | grid_key_dx<1> stop(size()-1); |
1715 | |
1716 | return base.getGPUIterator(start,stop,n_thr); |
1717 | } |
1718 | |
1719 | #endif |
1720 | /*! \brief Return the size of the message needed to pack this object |
1721 | * |
1722 | * \return The size |
1723 | * |
1724 | */ |
1725 | |
1726 | size_t packObjectSize() |
1727 | { |
1728 | return base.packObjectSize(); |
1729 | } |
1730 | |
1731 | /*! \brief Pack the object into the given pointer |
1732 | * |
1733 | * \param mem pointer |
1734 | * |
1735 | * \return the size of the packed message |
1736 | * |
1737 | */ |
1738 | size_t packObject(void * mem) |
1739 | { |
1740 | return base.packObject(mem); |
1741 | } |
1742 | |
1743 | /*! \brief Calculate the memory size required to allocate n elements |
1744 | * |
1745 | * Calculate the total size required to store n-elements in a vector |
1746 | * |
1747 | * \param n number of elements |
1748 | * \param e unused |
1749 | * |
1750 | * \return the size of the allocation number e |
1751 | * |
1752 | */ |
1753 | template<int ... prp> static inline size_t calculateMem(size_t n, size_t e) |
1754 | { |
1755 | if (n == 0) |
1756 | { |
1757 | return 0; |
1758 | } |
1759 | else |
1760 | { |
1761 | if (sizeof...(prp) == 0) |
1762 | return grow_p::grow(0,n) * sizeof(typename T::type); |
1763 | |
1764 | typedef object<typename object_creator<typename T::type,prp...>::type> prp_object; |
1765 | |
1766 | return grow_p::grow(0,n) * sizeof(prp_object); |
1767 | } |
1768 | } |
1769 | |
1770 | /*! \brief Calculate the memory size required to pack n elements |
1771 | * |
1772 | * Calculate the total size required to store n-elements in a vector |
1773 | * |
1774 | * \param n number of elements |
1775 | * \param e unused |
1776 | * |
1777 | * \return the size of the allocation number e |
1778 | * |
1779 | */ |
1780 | template<int ... prp> static inline size_t packMem(size_t n, size_t e) |
1781 | { |
1782 | if (sizeof...(prp) == 0) |
1783 | return n * sizeof(typename T::type); |
1784 | |
1785 | typedef object<typename object_creator<typename T::type,prp...>::type> prp_object; |
1786 | |
1787 | return n * sizeof(prp_object); |
1788 | } |
1789 | |
1790 | /*! \brief How many allocation are required to create n-elements |
1791 | * |
1792 | * \param n number of elements |
1793 | * |
1794 | * \return the number of allocations |
1795 | * |
1796 | */ |
1797 | inline static size_t calculateNMem(size_t n) |
1798 | { |
1799 | return 1; |
1800 | } |
1801 | |
1802 | /*! \brief Set the memory of the base structure using an object |
1803 | * |
1804 | * \param mem Memory object to use for allocation |
1805 | * |
1806 | */ |
1807 | template<unsigned int p = 0> void setMemory(Memory & mem) |
1808 | { |
1809 | base.template setMemory<p>(mem); |
1810 | } |
1811 | |
1812 | /*! \brief Set the memory of the base structure using an object |
1813 | * |
1814 | * \param mem Memory object to use for allocation |
1815 | * |
1816 | */ |
1817 | void setMemoryArray(Memory * mem) |
1818 | { |
1819 | base.setMemoryArray(mem); |
1820 | } |
1821 | |
1822 | /*! \brief Return the pointer that store the data |
1823 | * |
1824 | * \tparam property from which take the pointer |
1825 | * |
1826 | * \return the pointer that store the data |
1827 | * |
1828 | */ |
1829 | template<unsigned int p = 0> void * getPointer() |
1830 | { |
1831 | return base.template getPointer<p>(); |
1832 | } |
1833 | |
1834 | /*! \brief Return the pointer that store the data |
1835 | * |
1836 | * \return the pointer that store the data |
1837 | * |
1838 | */ |
1839 | template<unsigned int p = 0> const void * getPointer() const |
1840 | { |
1841 | return base.getPointer(); |
1842 | } |
1843 | |
1844 | /*! \brief This class has pointer inside |
1845 | * |
1846 | * \return false |
1847 | * |
1848 | */ |
1849 | static bool noPointers() |
1850 | { |
1851 | return false; |
1852 | } |
1853 | |
1854 | /*! \brief Internal function |
1855 | * |
1856 | * \return the size of the vector |
1857 | * |
1858 | */ |
1859 | const size_t & getInternal_v_size() const |
1860 | { |
1861 | return v_size; |
1862 | } |
1863 | |
1864 | /*! \brief Internal function |
1865 | * |
1866 | * \return the internal 1D grid base |
1867 | * |
1868 | */ |
1869 | const grid_base<1,T,Memory,layout_type> & getInternal_base() const |
1870 | { |
1871 | return base; |
1872 | } |
1873 | |
1874 | /*! \brief Copy the memory from host to device |
1875 | * |
1876 | * |
1877 | */ |
1878 | template<unsigned int ... prp> void hostToDevice() |
1879 | { |
1880 | base.template hostToDevice<prp ...>(); |
1881 | } |
1882 | |
1883 | /*! \brief Synchronize the memory buffer in the device with the memory in the host |
1884 | * |
1885 | * |
1886 | */ |
1887 | template<unsigned int ... prp> void deviceToHost() |
1888 | { |
1889 | base.template deviceToHost<prp ...>(); |
1890 | } |
1891 | |
1892 | |
1893 | /*! \brief Synchronize the memory buffer in the device with the memory in the host |
1894 | * |
1895 | * |
1896 | */ |
1897 | template<unsigned int ... prp> void deviceToHost(size_t start, size_t stop) |
1898 | { |
1899 | base.template deviceToHost<prp ...>(start,stop); |
1900 | } |
1901 | |
1902 | /*! \brief Synchronize the memory buffer in the device with the memory in the host |
1903 | * |
1904 | * |
1905 | */ |
1906 | template<unsigned int ... prp> void hostToDevice(size_t start, size_t stop) |
1907 | { |
1908 | base.template hostToDevice<prp ...>(start,stop); |
1909 | } |
1910 | |
1911 | |
1912 | /*! \brief Convert the grid into a data-structure compatible for computing into GPU |
1913 | * |
1914 | * The object created can be considered like a reference of the original |
1915 | * |
1916 | * \return an usable vector in the kernel |
1917 | * |
1918 | */ |
1919 | vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> toKernel() |
1920 | { |
1921 | vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> v(v_size,this->base.toKernel()); |
1922 | |
1923 | return v; |
1924 | } |
1925 | |
1926 | /*! \brief Convert the grid into a data-structure compatible for computing into GPU |
1927 | * |
1928 | * The object created can be considered like a reference of the original |
1929 | * |
1930 | * \return an usable vector in the kernel |
1931 | * |
1932 | */ |
1933 | const vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> toKernel() const |
1934 | { |
1935 | if (base.size() == 0) |
1936 | {std::cout << __FILE__ << ":" << __LINE__ << " Warning you are off-loading with toGPU a vector that seem to be empty or not initialized" << std::endl; } |
1937 | |
1938 | vector_gpu_ker<typename apply_transform<layout_base,T>::type,layout_base> v(v_size,this->base.toKernel()); |
1939 | |
1940 | return v; |
1941 | } |
1942 | |
1943 | /*! Convert this vector into a string |
1944 | * |
1945 | * \param prefix prefix to use for printing |
1946 | * |
1947 | * \return a string showing thid vector |
1948 | * |
1949 | */ |
1950 | template<unsigned int ... prps> |
1951 | const std::string toString(std::string prefix = std::string()) |
1952 | { |
1953 | std::stringstream ss; |
1954 | auto it = getIterator(); |
1955 | |
1956 | while (it.isNext()) |
1957 | { |
1958 | auto p = it.get(); |
1959 | |
1960 | ss << prefix; |
1961 | |
1962 | ss << prefix << " element[" << p << "]" << " " ; |
1963 | |
1964 | vector_printer<self_type,prps ...> vp(*this,p,ss); |
1965 | boost::mpl::for_each_ref<boost::mpl::range_c<int,0,sizeof...(prps)>>(vp); |
1966 | |
1967 | ss << std::endl; |
1968 | |
1969 | ++it; |
1970 | } |
1971 | |
1972 | return ss.str(); |
1973 | } |
1974 | |
1975 | void * internal_get_size_pointer() {return &v_size;} |
1976 | |
1977 | void print_size() |
1978 | { |
1979 | #ifndef DISABLE_ALL_RTTI |
1980 | std::cout << "the size of: " << demangle(typeid(self_type).name()) << " is " << sizeof(self_type) << std::endl; |
1981 | std::cout << " " << demangle(typeid(decltype(v_size)).name()) << ":" << sizeof(decltype(v_size)) << std::endl; |
1982 | std::cout << " " << demangle(typeid(decltype(base)).name()) << ":" << sizeof(decltype(base)) << std::endl; |
1983 | #endif |
1984 | } |
1985 | |
1986 | }; |
1987 | |
1988 | template <typename T> using vector_std = vector<T, HeapMemory, memory_traits_lin, openfpm::grow_policy_double, STD_VECTOR>; |
1989 | template<typename T> using vector_gpu = openfpm::vector<T,CudaMemory,memory_traits_inte>; |
1990 | template<typename T> using vector_gpu_single = openfpm::vector<T,CudaMemory,memory_traits_inte,openfpm::grow_policy_identity>; |
1991 | template<typename T> using vector_custd = vector<T, CudaMemory, memory_traits_inte, openfpm::grow_policy_double, STD_VECTOR>; |
1992 | } |
1993 | |
1994 | #endif |
1995 | |