8 #include <boost/compute/command_queue.hpp> 9 #include <boost/compute/container.hpp> 10 #include <boost/compute/context.hpp> 11 #include <boost/compute/type_traits.hpp> 12 #include <boost/compute/types/complex.hpp> 13 #include <boost/test/unit_test.hpp> 23 template <
typename T,
bool introduce_error = false>
27 reduce_sum(std::size_t
size, boost::compute::command_queue
const& queue)
28 :
jb::opencl::generic_reduce<reduce_sum<T, introduce_error>, T, T>(
33 static std::string initialize_body(
char const* lhs) {
34 if (introduce_error) {
35 return std::string(
"*") + lhs +
" = ; /* bad syntax error */";
37 return std::string(
"*") + lhs +
" = 0;";
42 transform_body(
char const* lhs,
char const* value,
char const*) {
43 return std::string(
"*") + lhs +
" = *" + value +
";";
47 static std::string combine_body(
char const* accumulated,
char const* value) {
48 return std::string(
"*") + accumulated +
" = *" + accumulated +
" + *" +
58 std::function<T()> create_random_generator(
unsigned int seed) {
59 std::mt19937 gen(seed);
60 std::uniform_int_distribution<T> dis(-1000, 1000);
61 using state_type = std::pair<std::mt19937, std::uniform_int_distribution<T>>;
62 std::shared_ptr<state_type> state(
new state_type(gen, dis));
63 return [state]() {
return state->second(state->first); };
67 std::function<float()> create_random_generator<float>(
unsigned int seed) {
68 std::mt19937 gen(seed);
69 std::uniform_real_distribution<float> dis(1, 2);
71 std::pair<std::mt19937, std::uniform_real_distribution<float>>;
72 std::shared_ptr<state_type> state(
new state_type(gen, dis));
73 return [state]() {
return state->second(state->first); };
77 std::function<double()> create_random_generator<double>(
unsigned int seed) {
78 std::mt19937 gen(seed);
79 std::uniform_real_distribution<double> dis(1, 2);
81 std::pair<std::mt19937, std::uniform_real_distribution<double>>;
82 std::shared_ptr<state_type> state(
new state_type(gen, dis));
83 return [state]() {
return state->second(state->first); };
86 template <
typename value_type,
bool introduce_error = false>
87 void check_generic_reduce_sized(std::size_t
size, std::size_t subset_size) {
88 BOOST_TEST_MESSAGE(
"Testing with size = " << size);
90 BOOST_TEST_MESSAGE(
"Running on device = " << device.name());
92 if (std::is_same<double, scalar_type>::value) {
93 if (not device.supports_extension(
"cl_khr_fp64")) {
95 "Test disabled, device (" << device.name()
96 <<
") does not support cl_khr_fp64, i.e., " 97 "double precision floating point");
102 boost::compute::context context(device);
103 boost::compute::command_queue queue(context, device);
105 unsigned int seed = std::random_device()();
106 BOOST_TEST_MESSAGE(
"SEED = " << seed);
107 auto generator = create_random_generator<scalar_type>(seed);
109 std::vector<value_type> asrc;
112 boost::compute::vector<value_type> a(size, context);
114 boost::compute::copy(asrc.begin(), asrc.begin() +
size, a.begin(), queue);
115 std::vector<value_type> acpy(size);
116 boost::compute::copy(a.begin(), a.begin() +
size, acpy.begin(), queue);
117 for (std::size_t i = 0; i != acpy.size(); ++i) {
118 JB_LOG(trace) <<
" " << i <<
" " << acpy[i] <<
" " << asrc[i];
121 reduce_sum<value_type, introduce_error> reducer(size, queue);
122 auto done = reducer.execute(a.begin(), a.begin() + subset_size);
125 value_type expected =
126 std::accumulate(asrc.begin(), asrc.begin() + subset_size, value_type(0));
127 value_type actual = *done.get();
130 "mismatched C++ vs. OpenCL results expected(C++)=" 131 << expected <<
" actual(OpenCL)=" << actual
132 <<
" delta=" << (actual - expected));
135 template <
typename value_type,
bool introduce_error = false>
136 void check_generic_reduce(std::size_t size) {
137 check_generic_reduce_sized<value_type, introduce_error>(
size,
size);
149 for (
int i = -N / 2; i != N / 2; ++i) {
150 std::size_t
const size = (1 << 8) + i;
151 check_generic_reduce<int>(
size);
162 for (
int i = -N / 2; i != N / 2; ++i) {
163 std::size_t
const size = (1 << 13) + i;
164 check_generic_reduce<int>(
size);
173 std::size_t
const size = (1 << 20);
174 check_generic_reduce<int>(
size);
182 std::size_t
const size = 1000 * 1000;
183 check_generic_reduce<int>(
size);
191 std::size_t
const size = 2 * 3 * 5 * 7 * 11 * 13 * 17 * 19;
192 check_generic_reduce<int>(
size);
200 std::size_t
const size = 2 * 3 * 5 * 7 * 11 * 13 * 17;
201 check_generic_reduce<float>(
size);
209 std::size_t
const size = 2 * 3 * 5 * 7 * 11 * 13;
210 check_generic_reduce<std::complex<float>>(
size);
218 std::size_t
const size = 2 * 3 * 5 * 7 * 11 * 13;
219 check_generic_reduce<std::complex<double>>(
size);
227 std::size_t
const size = 1000000;
228 std::size_t
const subset_size = size / 2;
229 check_generic_reduce_sized<double>(
size, subset_size);
236 std::size_t
const size = 1 << 18;
237 BOOST_CHECK_THROW((check_generic_reduce<float, true>(size)), std::exception);
void create_random_timeseries(generator &gen, int nsamples, timeseries &ts)
Create a simple timeseries where the values look like a random.
Implement a generic reducer for OpenCL.
boost::compute::device device_selector(config const &cfg)
Select an OpenCL device matching the current configuration.
BOOST_AUTO_TEST_CASE(generic_reduce_int_2e6)
The top-level namespace for the JayBeams library.
bool check_close_enough(value_t num_a, value_t num_b, int tol)
Given two numbers of the same integer type check if the difference is within a given tolerance...