From 5a000ac7b8f52045dd97da87ce1df871bba8a4fe Mon Sep 17 00:00:00 2001 From: Joe Todd Date: Wed, 25 Sep 2024 15:17:47 +0100 Subject: [PATCH 01/26] No constexpr construction in math tests bfloat16 can't be constexpr constructed --- .../test-e2e/syclcompat/math/math_compare.cpp | 36 ++++++------- sycl/test-e2e/syclcompat/math/math_ops.cpp | 54 +++++++++---------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/sycl/test-e2e/syclcompat/math/math_compare.cpp b/sycl/test-e2e/syclcompat/math/math_compare.cpp index c42b22b199888..11afc7420dc6d 100644 --- a/sycl/test-e2e/syclcompat/math/math_compare.cpp +++ b/sycl/test-e2e/syclcompat/math/math_compare.cpp @@ -56,7 +56,7 @@ template void test_compare() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(1.0); + const ValueT op1 = static_cast(1.0); ValueT op2 = sycl::nan(static_cast(0)); // 1.0 == 1.0 -> True @@ -102,7 +102,7 @@ template void test_compare_vec() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr Container op1 = {static_cast(1.0), + const Container op1 = {static_cast(1.0), static_cast(2.0)}; Container op2 = {static_cast(1.0), sycl::nan(static_cast(0))}; @@ -110,12 +110,12 @@ template void test_compare_vec() { // bool2 does not exist, 1.0 and 0.0 floats are used for true // and false instead. // 1.0 == 1.0, 2.0 == NaN -> {true, false} - constexpr Container res1 = {1.0, 0.0}; + const Container res1 = {1.0, 0.0}; BinaryOpTestLauncher(grid, threads) .template launch_test>(op1, op2, res1); // 1.0 != 1.0, 2.0 != NaN -> {false, false} - constexpr Container res2 = {0.0, 0.0}; + const Container res2 = {0.0, 0.0}; BinaryOpTestLauncher(grid, threads) .template launch_test>(op1, op2, res2); @@ -137,7 +137,7 @@ void test_unordered_compare() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(1.0); + const ValueT op1 = static_cast(1.0); ValueT op2 = sycl::nan(static_cast(0)); // Unordered comparison checks if either operand is NaN, or the binaryop holds @@ -183,7 +183,7 @@ template void test_unordered_compare_vec() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr Container op1 = {static_cast(1.0), + const Container op1 = {static_cast(1.0), static_cast(2.0)}; Container op2 = {static_cast(1.0), sycl::nan(static_cast(0))}; @@ -191,12 +191,12 @@ template void test_unordered_compare_vec() { // bool2 does not exist, 1.0 and 0.0 floats are used for true // and false instead. // 1.0 == 1.0, 2.0 == NaN -> {true, true} - constexpr Container res1 = {1.0, 1.0}; + const Container res1 = {1.0, 1.0}; BinaryOpTestLauncher(grid, threads) .template launch_test>( op1, op2, res1); // 1.0 != 1.0, 2.0 != NaN -> {false, true} - constexpr Container res2 = {0.0, 1.0}; + const Container res2 = {0.0, 1.0}; BinaryOpTestLauncher(grid, threads) .template launch_test>( op1, op2, res2); @@ -213,7 +213,7 @@ template void test_compare_both() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr Container op1 = {static_cast(1.0), + const Container op1 = {static_cast(1.0), static_cast(2.0)}; Container op2 = {static_cast(1.0), sycl::nan(static_cast(0))}; @@ -242,7 +242,7 @@ template void test_unordered_compare_both() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr Container op1 = {static_cast(1.0), + const Container op1 = {static_cast(1.0), static_cast(2.0)}; Container op2 = {static_cast(1.0), sycl::nan(static_cast(0))}; @@ -272,13 +272,13 @@ template void test_compare_mask() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr Container op1 = {static_cast(1.0), + const Container op1 = {static_cast(1.0), static_cast(2.0)}; - constexpr Container op2 = {static_cast(2.0), + const Container op2 = {static_cast(2.0), static_cast(1.0)}; - constexpr Container op3 = {static_cast(1.0), + const Container op3 = {static_cast(1.0), static_cast(3.0)}; - constexpr Container op4 = {static_cast(3.0), + const Container op4 = {static_cast(3.0), static_cast(2.0)}; Container op5 = {sycl::nan(static_cast(0)), sycl::nan(static_cast(0))}; @@ -320,13 +320,13 @@ template void test_unordered_compare_mask() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr Container op1 = {static_cast(1.0), + const Container op1 = {static_cast(1.0), static_cast(2.0)}; - constexpr Container op2 = {static_cast(2.0), + const Container op2 = {static_cast(2.0), static_cast(1.0)}; - constexpr Container op3 = {static_cast(1.0), + const Container op3 = {static_cast(1.0), static_cast(3.0)}; - constexpr Container op4 = {static_cast(3.0), + const Container op4 = {static_cast(3.0), static_cast(2.0)}; Container op5 = {sycl::nan(static_cast(0)), sycl::nan(static_cast(0))}; diff --git a/sycl/test-e2e/syclcompat/math/math_ops.cpp b/sycl/test-e2e/syclcompat/math/math_ops.cpp index 258c2a12ba1e5..d30bac3ed4b11 100644 --- a/sycl/test-e2e/syclcompat/math/math_ops.cpp +++ b/sycl/test-e2e/syclcompat/math/math_ops.cpp @@ -43,9 +43,9 @@ void test_syclcompat_max() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(5); - constexpr ValueU op2 = static_cast(10); - constexpr std::common_type_t res = static_cast(10); + const ValueT op1 = static_cast(5); + const ValueU op2 = static_cast(10); + const std::common_type_t res = static_cast(10); BinaryOpTestLauncher(grid, threads) .template launch_test>(op1, op2, res); @@ -63,9 +63,9 @@ void test_syclcompat_min() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(5); - constexpr ValueU op2 = static_cast(10); - constexpr std::common_type_t res = + const ValueT op1 = static_cast(5); + const ValueU op2 = static_cast(10); + const std::common_type_t res = static_cast>(5); BinaryOpTestLauncher(grid, threads) @@ -84,11 +84,11 @@ void test_syclcompat_fmin_nan() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(5); - constexpr ValueU op2 = static_cast(10); + const ValueT op1 = static_cast(5); + const ValueU op2 = static_cast(10); ValueU op3 = sycl::nan(static_cast(0)); - constexpr std::common_type_t res = + const std::common_type_t res = static_cast>(5); BinaryOpTestLauncher(grid, threads) @@ -110,11 +110,11 @@ void test_syclcompat_fmax_nan() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(5); - constexpr ValueU op2 = static_cast(10); + const ValueT op1 = static_cast(5); + const ValueU op2 = static_cast(10); ValueU op3 = sycl::nan(static_cast(0)); - constexpr std::common_type_t res = + const std::common_type_t res = static_cast>(10); BinaryOpTestLauncher(grid, threads) @@ -146,9 +146,9 @@ void test_syclcompat_pow() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; // 3 ** 3 = 27 - constexpr ValueT op1 = static_cast(3); - constexpr ValueU op2 = static_cast(3); - constexpr ValueT res = static_cast(27); + const ValueT op1 = static_cast(3); + const ValueU op2 = static_cast(3); + const ValueT res = static_cast(27); BinaryOpTestLauncher(grid, threads) .template launch_test>(op1, op2, res); @@ -165,25 +165,25 @@ template void test_syclcompat_relu() { constexpr syclcompat::dim3 threads{1}; // relu(3) = 3, relu(-value) = 0 - constexpr ValueT op1 = static_cast(3); - constexpr ValueT res1 = static_cast(3); + const ValueT op1 = static_cast(3); + const ValueT res1 = static_cast(3); UnaryOpTestLauncher(grid, threads) .template launch_test>(op1, res1); - constexpr ValueT op2 = static_cast(-3); - constexpr ValueT res2 = static_cast(0); + const ValueT op2 = static_cast(-3); + const ValueT res2 = static_cast(0); UnaryOpTestLauncher(grid, threads) .template launch_test>(op2, res2); using ValueU = sycl::vec; - constexpr ValueU op3{op1, op2}; - constexpr ValueU res3{res1, res2}; + const ValueU op3{op1, op2}; + const ValueU res3{res1, res2}; UnaryOpTestLauncher(grid, threads) .template launch_test>(op3, res3); using ValueV = sycl::marray; - constexpr ValueV op4{op1, op2}; - constexpr ValueV res4{res1, res2}; + const ValueV op4{op1, op2}; + const ValueV res4{res1, res2}; UnaryOpTestLauncher(grid, threads) .template launch_test>(op4, res4); } @@ -198,13 +198,13 @@ template void test_syclcompat_cbrt() { constexpr syclcompat::dim3 grid{1}; constexpr syclcompat::dim3 threads{1}; - constexpr ValueT op1 = static_cast(1); - constexpr ValueT res1 = static_cast(1); + const ValueT op1 = static_cast(1); + const ValueT res1 = static_cast(1); UnaryOpTestLauncher(grid, threads) .template launch_test>(op1, res1); - constexpr ValueT op2 = static_cast(64); - constexpr ValueT res2 = static_cast(4); + const ValueT op2 = static_cast(64); + const ValueT res2 = static_cast(4); UnaryOpTestLauncher(grid, threads) .template launch_test>(op2, res2); } From c32b2633eebb00b80591645fe03fcb9153dc2e37 Mon Sep 17 00:00:00 2001 From: Joe Todd Date: Thu, 26 Sep 2024 16:13:08 +0100 Subject: [PATCH 02/26] Add syclcompat::is_floating_point_v This includes sycl::half and sycl::ext::oneapi::bfloat16 --- sycl/doc/syclcompat/README.md | 21 +++++++++++++++++++++ sycl/include/syclcompat/traits.hpp | 17 +++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/sycl/doc/syclcompat/README.md b/sycl/doc/syclcompat/README.md index 6dd8708afeb62..059c0a8aecfe2 100644 --- a/sycl/doc/syclcompat/README.md +++ b/sycl/doc/syclcompat/README.md @@ -1690,7 +1690,27 @@ second operand, respectively. These three APIs return a single 32-bit value with the accumulated result, which is unsigned if both operands are `uint32_t` and signed otherwise. +Various maths functions are defined operate on any floating point types. +`syclcompat::is_floating_point_v` extends the standard library's +`std::is_floating_point_v` to include `sycl::half` and, where available, +`sycl::ext::oneapi::bfloat16`. + ```cpp +namespace syclcompat{ + +// Trait for extended floating point definition +template +struct is_floating_point : std::is_floating_point{}; + +template <> struct is_floating_point : std::true_type {}; + +#ifdef SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS +template <> struct is_floating_point : std::true_type {}; +#endif +template + +inline constexpr bool is_floating_point_v = is_floating_point::value; + inline unsigned int funnelshift_l(unsigned int low, unsigned int high, unsigned int shift); @@ -1889,6 +1909,7 @@ inline dot_product_acc_t dp2a_hi(T1 a, T2 b, template inline dot_product_acc_t dp4a(T1 a, T2 b, dot_product_acc_t c); +} // namespace syclcompat ``` `vectorized_binary` computes the `BinaryOperation` for two operands, diff --git a/sycl/include/syclcompat/traits.hpp b/sycl/include/syclcompat/traits.hpp index 2f389ccf79484..435b0df98a32d 100644 --- a/sycl/include/syclcompat/traits.hpp +++ b/sycl/include/syclcompat/traits.hpp @@ -22,6 +22,10 @@ #pragma once +#include +#ifdef SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS +#include "sycl/ext/oneapi/bfloat16.hpp" +#endif #include #include #include @@ -250,4 +254,17 @@ using are_all_props = std::conjunction< } // namespace experimental::detail +// Trait for extended floating point definition +template +struct is_floating_point : std::is_floating_point{}; + +template <> struct is_floating_point : std::true_type {}; + +#ifdef SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS +template <> struct is_floating_point : std::true_type {}; +#endif + +template +inline constexpr bool is_floating_point_v = is_floating_point::value; + } // namespace syclcompat From 9f28f62d1bb878a6b7d1305197554887a290d1e8 Mon Sep 17 00:00:00 2001 From: Joe Todd Date: Fri, 27 Sep 2024 11:54:34 +0100 Subject: [PATCH 03/26] Add bfloat16 to tests and generalize to container types - Adding bfloat to type lists - Making test fixtures work with sycl::vec and sycl::marray --- sycl/test-e2e/syclcompat/common.hpp | 38 +++++++++++++++++-- sycl/test-e2e/syclcompat/math/math_fixt.hpp | 41 ++++++++++++++++----- 2 files changed, 66 insertions(+), 13 deletions(-) diff --git a/sycl/test-e2e/syclcompat/common.hpp b/sycl/test-e2e/syclcompat/common.hpp index 368089e89e85a..7e3e5e7b3d70c 100644 --- a/sycl/test-e2e/syclcompat/common.hpp +++ b/sycl/test-e2e/syclcompat/common.hpp @@ -22,6 +22,10 @@ #pragma once +#include +#ifdef SYCL_EXT_ONEAPI_BFLOAT16_MATH_FUNCTIONS +#include "sycl/ext/oneapi/bfloat16.hpp" +#endif #include #include @@ -44,8 +48,36 @@ template void instantiate_all_types(Func &&f) { f(); \ }); +#define INSTANTIATE_ALL_CONTAINER_TYPES(tuple, container, f) \ + instantiate_all_types([](auto index) { \ + using T = std::tuple_element_t; \ + f(); \ + }); + using value_type_list = - std::tuple; + std::tuple; + +using fp_type_list = + std::tuple; -using fp_type_list = std::tuple; +using marray_type_list = + std::tuple; +using vec_type_list = std::tuple; diff --git a/sycl/test-e2e/syclcompat/math/math_fixt.hpp b/sycl/test-e2e/syclcompat/math/math_fixt.hpp index 8b395f94faca1..c40cd669f795e 100644 --- a/sycl/test-e2e/syclcompat/math/math_fixt.hpp +++ b/sycl/test-e2e/syclcompat/math/math_fixt.hpp @@ -51,8 +51,22 @@ static constexpr bool contained_is_floating_point_v = false; template static constexpr bool contained_is_floating_point_v< Container, std::void_t> = - std::is_floating_point_v || - std::is_same_v; + syclcompat::is_floating_point_v; + +template struct container_common_type; + +template