Skip to content

Commit f2f26bc

Browse files
authored
[SYCL][ESIMD] Add frem function (#15117)
Add support for the frem function. Support for this was just added to IGC, so we aren't using the driver in CI yet, so the test won't actually run. I manually tested single type which works with the version in `REQUIRES-INTEL-DRIVER`, but I found an issue in the driver with double so it's disabled in the test for now. Signed-off-by: Sarnie, Nick <nick.sarnie@intel.com>
1 parent 44c34c1 commit f2f26bc

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

sycl/include/sycl/ext/intel/experimental/esimd/detail/math_intrin.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ template <typename T, int N>
138138
extern __DPCPP_SYCL_EXTERNAL __ESIMD_raw_vec_t(T, N)
139139
__spirv_ocl_clz(__ESIMD_raw_vec_t(T, N) src0) __ESIMD_INTRIN_END;
140140

141+
template <typename T> extern __DPCPP_SYCL_EXTERNAL T __spirv_FRem(T);
142+
template <typename T, int N>
143+
extern __DPCPP_SYCL_EXTERNAL __ESIMD_raw_vec_t(T, N)
144+
__spirv_FRem(__ESIMD_raw_vec_t(T, N) src0,
145+
__ESIMD_raw_vec_t(T, N) src1) __ESIMD_INTRIN_END;
146+
141147
#undef __ESIMD_raw_vec_t
142148
#undef __ESIMD_cpp_vec_t
143149

sycl/include/sycl/ext/intel/experimental/esimd/math.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,18 @@ srnd(__ESIMD_NS::simd<float, N> src0, __ESIMD_NS::simd<uint16_t, N> src1) {
721721
return __esimd_srnd<N>(src0.data(), src1.data());
722722
}
723723

724+
/// frem - compute the remainder from floating point division.
725+
/// \param src0 the first operand to be used for division.
726+
/// \param src1 the second operand to be used for division.
727+
/// \return the remainder from the division.
728+
template <typename T, int N>
729+
ESIMD_INLINE __ESIMD_NS::simd<T, N> frem(__ESIMD_NS::simd<T, N> src0,
730+
__ESIMD_NS::simd<T, N> src1) {
731+
static_assert(std::is_same_v<T, float> || std::is_same_v<T, double>,
732+
"Element type must be float or double");
733+
return __spirv_FRem<T, N>(src0.data(), src1.data());
734+
}
735+
724736
/// @} sycl_esimd_math
725737

726738
/// @addtogroup sycl_esimd_logical

sycl/test-e2e/ESIMD/frem.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
//==---------------- frem.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+
// REQUIRES-INTEL-DRIVER: lin: 30623
9+
// RUN: %{build} -fsycl-device-code-split=per_kernel -o %t.out
10+
// RUN: %{run} %t.out
11+
12+
#include "esimd_test_utils.hpp"
13+
14+
#include <cmath>
15+
#include <sycl/ext/intel/experimental/esimd/math.hpp>
16+
17+
using namespace sycl;
18+
19+
template <typename T> bool test(queue q) {
20+
std::cout << "Running case: T=" << esimd_test::type_name<T>() << std::endl;
21+
constexpr unsigned Size = 16;
22+
constexpr unsigned VL = 16;
23+
24+
T *A = new T[Size];
25+
T *B = new T[Size];
26+
T *C = new T[Size];
27+
28+
for (unsigned i = 0; i < Size; ++i) {
29+
A[i] = i + 500;
30+
B[i] = i + 1;
31+
C[i] = 0.0f;
32+
}
33+
34+
try {
35+
buffer<T, 1> bufa(A, range<1>(Size));
36+
buffer<T, 1> bufb(B, range<1>(Size));
37+
buffer<T, 1> bufc(C, range<1>(Size));
38+
39+
auto e = q.submit([&](handler &cgh) {
40+
auto PA = bufa.template get_access<access::mode::read>(cgh);
41+
auto PB = bufb.template get_access<access::mode::read>(cgh);
42+
auto PC = bufc.template get_access<access::mode::write>(cgh);
43+
cgh.single_task([=]() SYCL_ESIMD_KERNEL {
44+
using namespace sycl::ext::intel::esimd;
45+
unsigned int offset = 0;
46+
simd<T, VL> va;
47+
va.copy_from(PA, offset);
48+
simd<T, VL> vb;
49+
vb.copy_from(PB, offset);
50+
simd<T, VL> vc = ext::intel::experimental::esimd::frem(va, vb);
51+
vc.copy_to(PC, offset);
52+
});
53+
});
54+
e.wait();
55+
} catch (sycl::exception const &e) {
56+
std::cout << "SYCL exception caught: " << e.what() << '\n';
57+
58+
delete[] A;
59+
delete[] B;
60+
delete[] C;
61+
return 0;
62+
}
63+
64+
int err_cnt = 0;
65+
66+
for (unsigned i = 0; i < Size; ++i) {
67+
T expected = std::remainder(A[i], B[i]);
68+
if (C[i] != expected) {
69+
if (++err_cnt < 10) {
70+
std::cout << "failed at index " << i << ", " << std::to_string(C[i])
71+
<< " != " << std::to_string(expected) << "\n";
72+
}
73+
}
74+
}
75+
if (err_cnt > 0) {
76+
std::cout << " pass rate: "
77+
<< ((float)(Size - err_cnt) / (float)Size) * 100.0f << "% ("
78+
<< (Size - err_cnt) << "/" << Size << ")\n";
79+
}
80+
81+
delete[] A;
82+
delete[] B;
83+
delete[] C;
84+
85+
std::cout << (err_cnt > 0 ? "FAILED\n" : "Passed\n");
86+
return err_cnt == 0;
87+
}
88+
89+
int main() {
90+
auto q = queue{gpu_selector_v};
91+
esimd_test::printTestLabel(q);
92+
bool passed = true;
93+
94+
passed &= test<float>(q);
95+
// TODO: Enable when driver issue fixed
96+
#if 0
97+
if (q.get_device().has(sycl::aspect::fp64))
98+
passed &= test<double>(q);
99+
#endif
100+
return passed ? 0 : 1;
101+
}

0 commit comments

Comments
 (0)