1 //  Copyright (c) 2017 Antoine Tran Tan
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <hpx/hpx_main.hpp>
7 #include <hpx/include/partitioned_vector_predef.hpp>
8 #include <hpx/include/partitioned_vector_view.hpp>
9 #include <hpx/lcos/spmd_block.hpp>
10 
11 #include <hpx/util/lightweight_test.hpp>
12 
13 #include <cstddef>
14 #include <string>
15 #include <type_traits>
16 #include <utility>
17 #include <vector>
18 
19 ///////////////////////////////////////////////////////////////////////////////
20 // The vector types to be used are defined in partitioned_vector module.
21 // HPX_REGISTER_PARTITIONED_VECTOR(double);
22 
bulk_test(hpx::lcos::spmd_block block,std::size_t size_x,std::size_t size_y,std::size_t size_z,std::size_t elt_size,std::string vec_name)23 void bulk_test( hpx::lcos::spmd_block block,
24                 std::size_t size_x,
25                 std::size_t size_y,
26                 std::size_t size_z,
27                 std::size_t elt_size,
28                 std::string vec_name)
29 {
30     using const_iterator
31         = typename std::vector<double>::const_iterator;
32     using vector_type
33         = hpx::partitioned_vector<double>;
34     using view_type
35         = hpx::partitioned_vector_view<double,3>;
36     using view_type_iterator
37         = typename view_type::iterator;
38     using const_view_type_iterator
39         = typename view_type::const_iterator;
40 
41     vector_type my_vector;
42     my_vector.connect_to(hpx::launch::sync, vec_name);
43 
44     view_type my_view(block,
45         my_vector.begin(), my_vector.end(), {size_x,size_y,size_z});
46 
47     int idx = 0;
48 
49     // Ensure that only one image is putting data into the different
50     // partitions
51     if(block.this_image() == 0)
52     {
53         // Traverse all the co-indexed elements
54         for(auto i = my_view.begin(); i != my_view.end(); i++)
55         {
56             // It's a Put operation
57             *i = std::vector<double>(elt_size,idx++);
58         }
59 
60         auto left_it  = my_view.begin();
61         auto right_it = my_view.cbegin();
62 
63         // Note: Useless computation, since we assign segments to themselves
64         for(; left_it != my_view.end(); left_it++, right_it++)
65         {
66             // Check that dereferencing iterator and const_iterator does not
67             // retrieve the same type
68             HPX_TEST((
69                 !std::is_same<decltype(*left_it),decltype(*right_it)>::value));
70 
71             // It's a Put operation
72             *left_it = *right_it;
73         }
74     }
75 
76     block.sync_all();
77 
78     if(block.this_image() == 0)
79     {
80         int idx = 0;
81 
82         for (std::size_t k = 0; k<size_z; k++)
83             for (std::size_t j = 0; j<size_y; j++)
84                 for (std::size_t i = 0; i<size_x; i++)
85                 {
86                     std::vector<double> result(elt_size,idx);
87 
88                     // It's a Get operation
89                     std::vector<double> value =
90                         (std::vector<double>)my_view(i,j,k);
91 
92                     const_iterator it1 = result.begin(), it2 = value.begin();
93                     const_iterator end1 = result.end();
94 
95                     for (; it1 != end1; ++it1, ++it2)
96                     {
97                         HPX_TEST_EQ(*it1, *it2);
98                     }
99 
100                     idx++;
101                 }
102 
103         idx = 0;
104 
105         // Re-check by traversing all the co-indexed elements
106         for(auto i = my_view.cbegin(); i != my_view.cend(); i++)
107         {
108             std::vector<double> result(elt_size,idx);
109 
110             // It's a Get operation
111             std::vector<double> value = (std::vector<double>)(*i);
112 
113             const_iterator it1 = result.begin(), it2 = value.begin();
114             const_iterator end1 = result.end();
115 
116             for (; it1 != end1; ++it1, ++it2)
117             {
118                 HPX_TEST_EQ(*it1, *it2);
119             }
120 
121             idx++;
122         }
123     }
124 }
125 HPX_PLAIN_ACTION(bulk_test, bulk_test_action);
126 
main()127 int main()
128 {
129     using vector_type
130         = hpx::partitioned_vector<double>;
131 
132     const std::size_t size_x = 32;
133     const std::size_t size_y = 4;
134     const std::size_t size_z = hpx::get_num_localities(hpx::launch::sync);
135 
136     const std::size_t elt_size = 4;
137     const std::size_t num_partitions  = size_x*size_y*size_z;
138 
139     std::size_t raw_size = num_partitions*elt_size;
140 
141     vector_type my_vector(raw_size,
142         hpx::container_layout( num_partitions, hpx::find_all_localities() ));
143 
144     std::string vec_name("my_vector");
145     my_vector.register_as(hpx::launch::sync, vec_name);
146 
147     hpx::future<void> join =
148         hpx::lcos::define_spmd_block("block", 4, bulk_test_action(),
149             size_x, size_y, size_z, elt_size, vec_name);
150 
151     join.get();
152 
153     return 0;
154 }
155