Skip to content

Commit c43ceb8

Browse files
committed
Add distributed::transform() algorithm
1 parent 72c478b commit c43ceb8

File tree

3 files changed

+399
-0
lines changed

3 files changed

+399
-0
lines changed
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2016 Jakub Szuppe <[email protected]>
3+
//
4+
// Distributed under the Boost Software License, Version 1.0
5+
// See accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt
7+
//
8+
// See http://boostorg.github.com/compute for more information.
9+
//---------------------------------------------------------------------------//
10+
11+
#ifndef BOOST_COMPUTE_DISTRIBUTED_TRANSFORM_HPP
12+
#define BOOST_COMPUTE_DISTRIBUTED_TRANSFORM_HPP
13+
14+
#include <boost/compute/iterator/transform_iterator.hpp>
15+
#include <boost/compute/iterator/zip_iterator.hpp>
16+
#include <boost/compute/functional/detail/unpack.hpp>
17+
18+
#include <boost/compute/distributed/command_queue.hpp>
19+
#include <boost/compute/distributed/vector.hpp>
20+
21+
namespace boost {
22+
namespace compute {
23+
namespace distributed {
24+
25+
/// Transforms all the elements from vector \p input using operator \p op
26+
/// and stores the results in \p result. The transform is performed
27+
/// asynchronously and it returns a vector of events, each assisted with
28+
/// transformation of successive parts of \p input.
29+
///
30+
/// \see distributed::transform()
31+
template<
32+
class InputType, class OutputType,
33+
weight_func weight, class Alloc,
34+
class UnaryOperator
35+
>
36+
inline std::vector<event>
37+
transform_async(const vector<InputType, weight, Alloc> &input,
38+
vector<OutputType, weight, Alloc> &result,
39+
UnaryOperator op,
40+
command_queue &queue)
41+
{
42+
BOOST_ASSERT(input.parts() == result.parts());
43+
BOOST_ASSERT(input.size() == result.size());
44+
45+
std::vector<event> events;
46+
events.reserve(input.parts());
47+
48+
for(size_t i = 0; i < input.parts(); i++)
49+
{
50+
event e =
51+
::boost::compute::copy_async(
52+
::boost::compute::make_transform_iterator(input.begin(i), op),
53+
::boost::compute::make_transform_iterator(input.end(i), op),
54+
result.begin(i),
55+
queue.get(i)
56+
).get_event();
57+
if(e.get()) {
58+
events.push_back(e);
59+
}
60+
}
61+
return events;
62+
}
63+
64+
/// \overload
65+
template<
66+
class InputType1, class InputType2, class OutputType,
67+
weight_func weight, class Alloc,
68+
class BinaryOperator
69+
>
70+
inline std::vector<event>
71+
transform_async(const vector<InputType1, weight, Alloc> &input1,
72+
const vector<InputType2, weight, Alloc> &input2,
73+
vector<OutputType, weight, Alloc> &result,
74+
BinaryOperator op,
75+
command_queue &queue)
76+
{
77+
BOOST_ASSERT(input1.parts() == input2.parts());
78+
BOOST_ASSERT(input1.parts() == result.parts());
79+
BOOST_ASSERT(input1.size() == input1.size());
80+
BOOST_ASSERT(input1.size() == result.size());
81+
82+
std::vector<event> events;
83+
events.reserve(input1.parts());
84+
85+
::boost::compute::detail::unpacked<BinaryOperator> unpacked_op =
86+
::boost::compute::detail::unpack(op);
87+
for(size_t i = 0; i < input1.parts(); i++)
88+
{
89+
event e =
90+
::boost::compute::copy_async(
91+
::boost::compute::make_transform_iterator(
92+
::boost::compute::make_zip_iterator(
93+
boost::make_tuple(input1.begin(i), input2.begin(i))
94+
),
95+
unpacked_op
96+
),
97+
::boost::compute::make_transform_iterator(
98+
::boost::compute::make_zip_iterator(
99+
boost::make_tuple(input1.end(i), input2.end(i))
100+
),
101+
unpacked_op
102+
),
103+
result.begin(i),
104+
queue.get(i)
105+
).get_event();
106+
if(e.get()) {
107+
events.push_back(e);
108+
}
109+
}
110+
return events;
111+
}
112+
113+
/// Transforms all the elements from vector \p input using operator \p op
114+
/// and stores the results in \p result.
115+
///
116+
/// \see distributed::transform_async()
117+
template<
118+
class InputType, weight_func weight, class Alloc, class OutputType,
119+
class UnaryOperator
120+
>
121+
inline void
122+
transform(const vector<InputType, weight, Alloc> &input,
123+
vector<OutputType, weight, Alloc> &output,
124+
UnaryOperator op,
125+
command_queue &queue)
126+
{
127+
std::vector<event> events =
128+
transform_async(
129+
input, output, op, queue
130+
);
131+
for(size_t i = 0; i < events.size(); i++) {
132+
events[i].wait();
133+
}
134+
}
135+
136+
/// \overload
137+
template<
138+
class InputType1, class InputType2, class OutputType,
139+
weight_func weight, class Alloc,
140+
class BinaryOperator
141+
>
142+
inline void
143+
transform(const vector<InputType1, weight, Alloc> &input1,
144+
const vector<InputType2, weight, Alloc> &input2,
145+
vector<OutputType, weight, Alloc> &output,
146+
BinaryOperator op,
147+
command_queue &queue)
148+
{
149+
std::vector<event> events =
150+
transform_async(
151+
input1, input2, output, op, queue
152+
);
153+
for(size_t i = 0; i < events.size(); i++) {
154+
events[i].wait();
155+
}
156+
}
157+
158+
} // end distributed namespace
159+
} // end compute namespace
160+
} // end boost namespace
161+
162+
#endif /* BOOST_COMPUTE_DISTRIBUTED_TRANSFORM_HPP */

test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ add_compute_test("distributed.context" test_distributed_context.cpp)
8585
add_compute_test("distributed.command_queue" test_distributed_command_queue.cpp)
8686
add_compute_test("distributed.vector" test_distributed_vector.cpp)
8787
add_compute_test("distributed.copy" test_distributed_copy.cpp)
88+
add_compute_test("distributed.transform" test_distributed_transform.cpp)
8889

8990
add_compute_test("utility.extents" test_extents.cpp)
9091
add_compute_test("utility.invoke" test_invoke.cpp)

0 commit comments

Comments
 (0)