1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013-2014 Kyle Lutz <kyle.r.lutz@gmail.com>
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 #include <boost/compute/core.hpp>
12 #include <boost/compute/closure.hpp>
13 #include <boost/compute/algorithm/copy_if.hpp>
14 #include <boost/compute/container/vector.hpp>
15 #include <boost/compute/random/default_random_engine.hpp>
16 #include <boost/compute/random/uniform_int_distribution.hpp>
17 #include <boost/compute/random/uniform_real_distribution.hpp>
18 
19 #include "perf.hpp"
20 
21 namespace compute = boost::compute;
22 
test_copy_if_odd(compute::command_queue & queue)23 void test_copy_if_odd(compute::command_queue &queue)
24 {
25     // create input and output vectors on the device
26     const compute::context &context = queue.get_context();
27     compute::vector<int> input(PERF_N, context);
28     compute::vector<int> output(PERF_N, context);
29 
30     // generate random numbers between 1 and 10
31     compute::default_random_engine rng(queue);
32     compute::uniform_int_distribution<int> d(1, 10);
33     d.generate(input.begin(), input.end(), rng, queue);
34 
35     BOOST_COMPUTE_FUNCTION(bool, is_odd, (int x),
36     {
37         return x & 1;
38     });
39 
40     perf_timer t;
41     for(size_t trial = 0; trial < PERF_TRIALS; trial++){
42         t.start();
43         compute::vector<int>::iterator i = compute::copy_if(
44             input.begin(), input.end(), output.begin(), is_odd, queue
45         );
46         queue.finish();
47         t.stop();
48 
49         float ratio = float(std::distance(output.begin(), i)) / PERF_N;
50         if(PERF_N > 1000 && (ratio < 0.45f || ratio > 0.55f)){
51             std::cerr << "error: ratio is " << ratio << std::endl;
52             std::cerr << "error: ratio should be around 45-55%" << std::endl;
53         }
54     }
55     std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
56 }
57 
test_copy_if_in_sphere(compute::command_queue & queue)58 void test_copy_if_in_sphere(compute::command_queue &queue)
59 {
60     using boost::compute::float4_;
61 
62     // create input and output vectors on the device
63     const compute::context &context = queue.get_context();
64     compute::vector<float4_> input_points(PERF_N, context);
65     compute::vector<float4_> output_points(PERF_N, context);
66 
67     // generate random numbers in a cube
68     float radius = 5.0f;
69     compute::default_random_engine rng(queue);
70     compute::uniform_real_distribution<float> d(-radius, +radius);
71     d.generate(
72         compute::make_buffer_iterator<float>(input_points.get_buffer(), 0),
73         compute::make_buffer_iterator<float>(input_points.get_buffer(), PERF_N * 4),
74         rng,
75         queue
76     );
77 
78     // predicate which returns true if the point lies within the sphere
79     BOOST_COMPUTE_CLOSURE(bool, is_in_sphere, (float4_ point), (radius),
80     {
81         // ignore fourth component
82         point.w = 0;
83 
84         return length(point) < radius;
85     });
86 
87     perf_timer t;
88     for(size_t trial = 0; trial < PERF_TRIALS; trial++){
89         t.start();
90         compute::vector<float4_>::iterator i = compute::copy_if(
91             input_points.begin(),
92             input_points.end(),
93             output_points.begin(),
94             is_in_sphere,
95             queue
96         );
97         queue.finish();
98         t.stop();
99 
100         float ratio = float(std::distance(output_points.begin(), i)) / PERF_N;
101         if(PERF_N > 1000 && (ratio < 0.5f || ratio > 0.6f)){
102             std::cerr << "error: ratio is " << ratio << std::endl;
103             std::cerr << "error: ratio should be around 50-60%" << std::endl;
104         }
105     }
106     std::cout << "time: " << t.min_time() / 1e6 << " ms" << std::endl;
107 }
108 
main(int argc,char * argv[])109 int main(int argc, char *argv[])
110 {
111     perf_parse_args(argc, argv);
112 
113     // setup context and queue for the default device
114     boost::compute::device device = boost::compute::system::default_device();
115     boost::compute::context context(device);
116     boost::compute::command_queue queue(context, device);
117     std::cout << "device: " << device.name() << std::endl;
118 
119     test_copy_if_odd(queue);
120 
121     return 0;
122 }
123