1 #define BOOST_TEST_MODULE ReduceByKey
2 #include <algorithm>
3 #include <numeric>
4 #include <boost/test/unit_test.hpp>
5 #include <vexcl/vector.hpp>
6 #include <vexcl/scan_by_key.hpp>
7 #include "context_setup.hpp"
8
nvidia_cl(const vex::Context & ctx)9 bool nvidia_cl(const vex::Context &ctx) {
10 #if defined(VEXCL_BACKEND_CUDA) || defined(VEXCL_BACKEND_JIT)
11 return false;
12 #else
13 return vex::Filter::Platform("NVIDIA")(ctx.device(0));
14 #endif
15 }
16
BOOST_AUTO_TEST_CASE(sbk)17 BOOST_AUTO_TEST_CASE(sbk)
18 {
19 // NVIDIA OpenCL compiler crashes on scan_by_key kernels.
20 if (nvidia_cl(ctx)) return;
21
22 const int n = 1000;
23
24 std::vector<int> x = random_vector<int>(n);
25 std::vector<int> y = random_vector<int>(n);
26
27 std::sort(x.begin(), x.end());
28
29 std::vector<vex::backend::command_queue> queue(1, ctx.queue(0));
30
31 vex::vector<int> ikeys(queue, x);
32 vex::vector<int> ivals(queue, y);
33 vex::vector<int> ovals(queue, n);
34
35 vex::inclusive_scan_by_key(ikeys, ivals, ovals);
36
37 check_sample(ovals, [&](size_t i, int v) {
38 if (i == 0)
39 BOOST_CHECK_EQUAL(v, y[i]);
40 else if (x[i-1] == x[i])
41 BOOST_CHECK_EQUAL(
42 y[i],
43 static_cast<int>(ovals[i]) - static_cast<int>(ovals[i-1])
44 );
45 else
46 BOOST_CHECK_EQUAL(v, y[i]);
47 });
48
49 vex::exclusive_scan_by_key(ikeys, ivals, ovals);
50
51 check_sample(ovals, [&](size_t i, int v) {
52 if (i == 0)
53 BOOST_CHECK_EQUAL(v, 0);
54 else if (x[i-1] == x[i])
55 BOOST_CHECK_EQUAL(
56 y[i-1],
57 static_cast<int>(ovals[i]) - static_cast<int>(ovals[i-1])
58 );
59 else
60 BOOST_CHECK_EQUAL(v, 0);
61 });
62 }
63
BOOST_AUTO_TEST_CASE(sbk_tuple)64 BOOST_AUTO_TEST_CASE(sbk_tuple)
65 {
66 // NVIDIA OpenCL compiler crashes on scan_by_key kernels.
67 if (nvidia_cl(ctx)) return;
68
69 const int n = 1000;
70
71 std::vector<int> x1 = random_vector<int>(n);
72 std::vector<int> x2 = random_vector<int>(n);
73 std::vector<int> y = random_vector<int>(n);
74
75 std::sort(x1.begin(), x1.end());
76 std::sort(x2.begin(), x2.end());
77
78 std::vector<vex::backend::command_queue> queue(1, ctx.queue(0));
79
80 vex::vector<int> ikey1(queue, x1);
81 vex::vector<int> ikey2(queue, x2);
82 vex::vector<int> ivals(queue, y);
83 vex::vector<int> ovals(queue, n);
84
85 VEX_FUNCTION(bool, equal, (int, a1)(int, a2)(int, b1)(int, b2),
86 return a1 == b1 && a2 == b2;
87 );
88
89 VEX_FUNCTION(int, plus, (int, x)(int, y),
90 return x + y;
91 );
92
93 vex::inclusive_scan_by_key(
94 boost::fusion::vector_tie(ikey1, ikey2), ivals, ovals,
95 equal, plus);
96
97 check_sample(ovals, [&](size_t i, int v) {
98 if (i == 0)
99 BOOST_CHECK_EQUAL(v, y[i]);
100 else if (std::make_tuple(x1[i-1], x2[i-1]) == std::make_tuple(x1[i], x2[i]))
101 BOOST_CHECK_EQUAL(
102 y[i],
103 static_cast<int>(ovals[i]) - static_cast<int>(ovals[i-1])
104 );
105 else
106 BOOST_CHECK_EQUAL(v, y[i]);
107 });
108
109 vex::exclusive_scan_by_key(
110 boost::fusion::vector_tie(ikey1, ikey2), ivals, ovals,
111 equal, plus);
112
113 check_sample(ovals, [&](size_t i, int v) {
114 if (i == 0)
115 BOOST_CHECK_EQUAL(v, 0);
116 else if (std::make_tuple(x1[i-1], x2[i-1]) == std::make_tuple(x1[i], x2[i]))
117 BOOST_CHECK_EQUAL(
118 y[i-1],
119 static_cast<int>(ovals[i]) - static_cast<int>(ovals[i-1])
120 );
121 else
122 BOOST_CHECK_EQUAL(v, 0);
123 });
124 }
125
126 BOOST_AUTO_TEST_SUITE_END()
127