Skip to content

Commit a3a9dd0

Browse files
authored
[SYCL][ESIMD] Fix assignment to private globals (#9608)
The implicitly generated copy assignment operator doesn't do what we need because we need vloads and vstores for globals. Add an explicit copy assignment operator to do what we want. Note this makes the `simd` and `simd_mask` classes not trivially move assignable or copy assignable, but that is a fundamental requirement to support globals, so it being trivially assignable was a bug. Signed-off-by: Sarnie, Nick <[email protected]>
1 parent a6b7cb7 commit a3a9dd0

File tree

6 files changed

+202
-2
lines changed

6 files changed

+202
-2
lines changed

sycl/include/sycl/ext/intel/esimd/detail/simd_mask_impl.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ class simd_mask_impl
132132
return *this;
133133
}
134134

135+
/// Copy assignment operator.
136+
simd_mask_impl &operator=(const simd_mask_impl &other) noexcept {
137+
return base_type::operator=(other);
138+
}
139+
135140
/// Conversion to boolean. Available only when the number of elements is 1.
136141
/// @return true if the element is non-zero, false otherwise.
137142
template <class T1 = simd_mask_impl,

sycl/include/sycl/ext/intel/esimd/detail/simd_obj_impl.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,12 @@ class simd_obj_impl {
347347
copy_from(acc, offset, Flags{});
348348
}
349349

350+
/// Copy assignment operator.
351+
Derived &operator=(const simd_obj_impl &other) noexcept {
352+
set(other.data());
353+
return cast_this_to_derived();
354+
}
355+
350356
/// Type conversion into a scalar:
351357
/// <code><simd_obj_impl<RawTy, 1, simd<Ty,1>></code> to \c Ty.
352358
template <typename T = simd_obj_impl,

sycl/include/sycl/ext/intel/esimd/simd.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,11 @@ class simd : public detail::simd_obj_impl<
126126
return sycl::ext::oneapi::experimental::simd<Ty, N1>(base_type::data());
127127
}
128128

129+
/// Copy assignment operator.
130+
simd &operator=(const simd &other) noexcept {
131+
return base_type::operator=(other);
132+
}
133+
129134
/// Prefix increment, increments elements of this object.
130135
/// @return Reference to this object.
131136
simd &operator++() {
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//==--- operator_assignment_glb.cpp - DPC++ ESIMD on-device test ---==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===---------------------------------------------------------------===//
8+
// RUN: %{build} -o %t.out
9+
// RUN: %{run} %t.out
10+
#include "common.hpp"
11+
#include <iostream>
12+
#include <sycl/ext/intel/esimd.hpp>
13+
#include <sycl/sycl.hpp>
14+
15+
using namespace sycl;
16+
using namespace sycl::ext::intel::esimd;
17+
18+
constexpr unsigned VL = 16;
19+
20+
ESIMD_PRIVATE ESIMD_REGISTER(0) simd<float, VL> va;
21+
ESIMD_PRIVATE ESIMD_REGISTER(0) simd<float, VL> vc;
22+
23+
int main(void) {
24+
constexpr unsigned Size = 1024 * 128;
25+
26+
std::vector<float> A(Size);
27+
std::vector<float> B(Size);
28+
std::vector<float> C(Size);
29+
30+
for (unsigned i = 0; i < Size; ++i) {
31+
A[i] = B[i] = i;
32+
C[i] = 0.0f;
33+
}
34+
35+
buffer<float, 1> bufa(A.data(), A.size());
36+
buffer<float, 1> bufb(B.data(), B.size());
37+
buffer<float, 1> bufc(C.data(), C.size());
38+
39+
try {
40+
// We need that many workgroups
41+
range<1> GlobalRange{Size / VL};
42+
43+
// We need that many threads in each group
44+
range<1> LocalRange{1};
45+
46+
queue q(esimd_test::ESIMDSelector, esimd_test::createExceptionHandler());
47+
48+
auto dev = q.get_device();
49+
std::cout << "Running on " << dev.get_info<info::device::name>() << "\n";
50+
51+
auto e = q.submit([&](handler &cgh) {
52+
auto PA = bufa.get_access<access::mode::read>(cgh);
53+
auto PB = bufb.get_access<access::mode::read>(cgh);
54+
auto PC = bufc.get_access<access::mode::write>(cgh);
55+
cgh.parallel_for<class Test>(
56+
GlobalRange * LocalRange, [=](id<1> i) SYCL_ESIMD_KERNEL {
57+
using namespace sycl::ext::intel::esimd;
58+
unsigned int offset = i * VL * sizeof(float);
59+
va.copy_from(PA, offset);
60+
simd<float, VL> vb;
61+
vb.copy_from(PB, offset);
62+
vc = va + vb;
63+
vc.copy_to(PC, offset);
64+
});
65+
});
66+
e.wait();
67+
} catch (sycl::exception const &e) {
68+
std::cout << "SYCL exception caught: " << e.what() << '\n';
69+
70+
return 1;
71+
}
72+
73+
sycl::host_accessor A_acc(bufa);
74+
sycl::host_accessor B_acc(bufb);
75+
sycl::host_accessor C_acc(bufc);
76+
int err_cnt = 0;
77+
78+
for (unsigned i = 0; i < Size; ++i) {
79+
if (A_acc[i] + B_acc[i] != C_acc[i]) {
80+
if (++err_cnt < 10) {
81+
std::cout << "failed at index " << i << ", " << C_acc[i]
82+
<< " != " << A_acc[i] << " + " << B_acc[i] << "\n";
83+
}
84+
}
85+
}
86+
if (err_cnt > 0) {
87+
std::cout << " pass rate: "
88+
<< ((float)(Size - err_cnt) / (float)Size) * 100.0f << "% ("
89+
<< (Size - err_cnt) << "/" << Size << ")\n";
90+
}
91+
92+
std::cout << (err_cnt > 0 ? "FAILED\n" : "Passed\n");
93+
return err_cnt > 0 ? 1 : 0;
94+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//==- operator_assignment_glb_mask.cpp - DPC++ ESIMD on-device test -==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===---------------------------------------------------------------===//
8+
// TODO: Remove when GPU driver is updated
9+
// REQUIRES: gpu-intel-pvc
10+
// RUN: %{build} -o %t.out
11+
// RUN: %{run} %t.out
12+
#include "common.hpp"
13+
#include <iostream>
14+
#include <sycl/ext/intel/esimd.hpp>
15+
#include <sycl/sycl.hpp>
16+
17+
using namespace sycl;
18+
using namespace sycl::ext::intel::esimd;
19+
20+
constexpr unsigned VL = 16;
21+
22+
ESIMD_PRIVATE ESIMD_REGISTER(0) simd_mask<VL> va;
23+
ESIMD_PRIVATE ESIMD_REGISTER(0) simd_mask<VL> vb;
24+
25+
int main(void) {
26+
constexpr unsigned Size = 1024;
27+
28+
std::vector<unsigned short> A(Size);
29+
std::vector<unsigned short> B(Size);
30+
31+
for (unsigned i = 0; i < Size; ++i) {
32+
A[i] = i % std::numeric_limits<unsigned short>::max();
33+
B[i] = 0;
34+
}
35+
36+
buffer<unsigned short, 1> bufa(A.data(), A.size());
37+
buffer<unsigned short, 1> bufb(B.data(), B.size());
38+
39+
try {
40+
// We need that many workgroups
41+
range<1> GlobalRange{Size / VL};
42+
43+
// We need that many threads in each group
44+
range<1> LocalRange{1};
45+
46+
queue q(esimd_test::ESIMDSelector, esimd_test::createExceptionHandler());
47+
48+
auto dev = q.get_device();
49+
std::cout << "Running on " << dev.get_info<info::device::name>() << "\n";
50+
51+
auto e = q.submit([&](handler &cgh) {
52+
auto PA = bufa.get_access<access::mode::read>(cgh);
53+
auto PB = bufb.get_access<access::mode::write>(cgh);
54+
cgh.parallel_for<class Test>(
55+
GlobalRange * LocalRange, [=](id<1> i) SYCL_ESIMD_KERNEL {
56+
using namespace sycl::ext::intel::esimd;
57+
unsigned int offset = i * VL * sizeof(unsigned short);
58+
va.copy_from(PA, offset);
59+
vb = va;
60+
vb.copy_to(PB, offset);
61+
});
62+
});
63+
e.wait();
64+
} catch (sycl::exception const &e) {
65+
std::cout << "SYCL exception caught: " << e.what() << '\n';
66+
67+
return 1;
68+
}
69+
70+
sycl::host_accessor A_acc(bufa);
71+
sycl::host_accessor B_acc(bufb);
72+
int err_cnt = 0;
73+
74+
for (unsigned i = 0; i < Size; ++i) {
75+
if (A_acc[i] != B_acc[i]) {
76+
if (++err_cnt < 10) {
77+
std::cout << "failed at index " << i << ", " << B_acc[i]
78+
<< " != " << A_acc[i] << "\n";
79+
}
80+
}
81+
}
82+
if (err_cnt > 0) {
83+
std::cout << " pass rate: "
84+
<< ((float)(Size - err_cnt) / (float)Size) * 100.0f << "% ("
85+
<< (Size - err_cnt) << "/" << Size << ")\n";
86+
}
87+
88+
std::cout << (err_cnt > 0 ? "FAILED\n" : "Passed\n");
89+
return err_cnt > 0 ? 1 : 0;
90+
}

sycl/test/esimd/simd.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ template <class T> void test_simd_class_traits() SYCL_ESIMD_FUNCTION {
3333
"type trait mismatch");
3434
static_assert(std::is_copy_assignable<simd<T, 4>>::value,
3535
"type trait mismatch");
36-
static_assert(std::is_trivially_copy_assignable<simd<T, 4>>::value,
36+
static_assert(!std::is_trivially_copy_assignable<simd<T, 4>>::value,
3737
"type trait mismatch");
3838
static_assert(std::is_move_assignable<simd<T, 4>>::value,
3939
"type trait mismatch");
40-
static_assert(std::is_trivially_move_assignable<simd<T, 4>>::value,
40+
static_assert(!std::is_trivially_move_assignable<simd<T, 4>>::value,
4141
"type trait mismatch");
4242
}
4343

0 commit comments

Comments
 (0)