forked from intel/llvm-test-suite
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreduction_nd_s1_rw.cpp
More file actions
122 lines (103 loc) · 4.52 KB
/
Copy pathreduction_nd_s1_rw.cpp
File metadata and controls
122 lines (103 loc) · 4.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple %s -o %t.out
// RUN: %CPU_RUN_PLACEHOLDER %t.out
// RUN: %GPU_RUN_PLACEHOLDER %t.out
// RUN: %ACC_RUN_PLACEHOLDER %t.out
// This test performs basic checks of parallel_for(nd_range, reduction, func)
// with reductions initialized with 1-dimensional read_write accessor
// accessing 1 element buffer.
// This test fails with exceeded time out on Windows with OpenCL, temporarily
// disabling
// UNSUPPORTED: windows && opencl
#include "reduction_utils.hpp"
#include <CL/sycl.hpp>
#include <cassert>
using namespace cl::sycl;
template <typename T, bool B> class KName;
template <typename Name, bool IsSYCL2020Mode, typename T, int Dim,
class BinaryOperation>
void test(T Identity, size_t WGSize, size_t NWItems) {
buffer<T, 1> InBuf(NWItems);
buffer<T, 1> OutBuf(1);
// Initialize.
BinaryOperation BOp;
T CorrectOut;
initInputData(InBuf, CorrectOut, Identity, BOp, NWItems);
(OutBuf.template get_access<access::mode::write>())[0] = Identity;
// Compute.
queue Q;
nd_range<1> NDRange(range<1>{NWItems}, range<1>{WGSize});
if constexpr (IsSYCL2020Mode) {
Q.submit([&](handler &CGH) {
auto In = InBuf.template get_access<access::mode::read>(CGH);
auto Redu = sycl::reduction(OutBuf, CGH, Identity, BOp);
CGH.parallel_for<Name>(NDRange, Redu, [=](nd_item<1> NDIt, auto &Sum) {
Sum.combine(In[NDIt.get_global_linear_id()]);
});
});
} else {
Q.submit([&](handler &CGH) {
auto In = InBuf.template get_access<access::mode::read>(CGH);
accessor<T, Dim, access::mode::read_write, access::target::global_buffer>
Out(OutBuf, CGH);
auto Redu = ONEAPI::reduction(Out, Identity, BOp);
range<1> GlobalRange(NWItems);
range<1> LocalRange(WGSize);
nd_range<1> NDRange(GlobalRange, LocalRange);
CGH.parallel_for<Name>(NDRange, Redu, [=](nd_item<1> NDIt, auto &Sum) {
Sum.combine(In[NDIt.get_global_linear_id()]);
});
});
}
// Check correctness.
auto Out = OutBuf.template get_access<access::mode::read>();
T ComputedOut = *(Out.get_pointer());
if (ComputedOut != CorrectOut) {
std::cout << "NWItems = " << NWItems << ", WGSize = " << WGSize << "\n";
std::cout << "Computed value: " << ComputedOut
<< ", Expected value: " << CorrectOut << "\n";
assert(0 && "Wrong value.");
}
}
template <typename Name, typename T, int Dim, class BinaryOperation>
void testBoth(T Identity, size_t WGSize, size_t NWItems) {
test<KName<Name, false>, false, T, Dim, BinaryOperation>(Identity, WGSize,
NWItems);
test<KName<Name, true>, true, T, Dim, BinaryOperation>(Identity, WGSize,
NWItems);
}
int main() {
// Check some less standards WG sizes and corner cases first.
testBoth<class A, int, 1, ONEAPI::plus<int>>(0, 2, 2);
testBoth<class B, int, 1, ONEAPI::plus<int>>(0, 7, 7);
testBoth<class C, int, 1, ONEAPI::plus<int>>(0, 9, 18);
testBoth<class D, int, 1, ONEAPI::plus<int>>(0, 49, 49 * 5);
// Try some power-of-two work-group sizes.
testBoth<class E, int, 1, ONEAPI::plus<int>>(0, 2, 64);
testBoth<class F, int, 1, ONEAPI::plus<int>>(0, 4, 64);
testBoth<class G, int, 1, ONEAPI::plus<int>>(0, 8, 128);
testBoth<class H, int, 1, ONEAPI::plus<int>>(0, 16, 256);
testBoth<class I, int, 1, ONEAPI::plus<int>>(0, 32, 256);
testBoth<class J, int, 1, ONEAPI::plus<int>>(0, 64, 256);
testBoth<class K, int, 1, ONEAPI::plus<int>>(0, 128, 256);
testBoth<class L, int, 1, ONEAPI::plus<int>>(0, 256, 256);
// Check with various operations.
testBoth<class M, int, 1, std::multiplies<int>>(1, 8, 256);
testBoth<class N, int, 1, ONEAPI::bit_or<int>>(0, 8, 256);
testBoth<class O, int, 1, ONEAPI::bit_xor<int>>(0, 8, 256);
testBoth<class P, int, 1, ONEAPI::bit_and<int>>(~0, 8, 256);
testBoth<class Q, int, 1, ONEAPI::minimum<int>>(
(std::numeric_limits<int>::max)(), 8, 256);
testBoth<class R, int, 1, ONEAPI::maximum<int>>(
(std::numeric_limits<int>::min)(), 8, 256);
// Check with various types.
testBoth<class S, float, 1, std::multiplies<float>>(1, 8, 256);
testBoth<class T, float, 1, ONEAPI::minimum<float>>(
getMaximumFPValue<float>(), 1, 16);
testBoth<class U, float, 1, ONEAPI::maximum<float>>(
getMinimumFPValue<float>(), 8, 256);
// Check with CUSTOM type.
testBoth<class V, CustomVec<long long>, 1, CustomVecPlus<long long>>(
CustomVec<long long>(0), 8, 256);
std::cout << "Test passed\n";
return 0;
}