Skip to content

[SYCL] Implement SYCL_ONEAPI_accessor_properties #2456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Sep 18, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions sycl/include/CL/sycl/ONEAPI/accessor_property_list.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
//==----- accessor_property_list.hpp --- SYCL accessor property list -------==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#pragma once

#include <CL/sycl/access/access.hpp>
#include <CL/sycl/detail/common.hpp>
#include <CL/sycl/detail/property_list_base.hpp>
#include <CL/sycl/property_list.hpp>

#include <type_traits>

__SYCL_INLINE_NAMESPACE(cl) {
namespace sycl {
namespace detail {
// This helper template must be specialized for nestend instance template
// of each compile-time-constant property.
template <typename T> struct IsCxPropertyInstance : std::false_type {};
} // namespace detail
namespace ONEAPI {

template <typename T> struct is_compile_time_property : std::false_type {};

/// Objects of the accessor_property_list class are containers for the SYCL
/// properties.
///
/// Unlike \c property_list, accessor_property_list can take
/// compile-time-constant properties.
///
/// \sa accessor
/// \sa property_list
///
/// \ingroup sycl_api
template <typename... PropsT>
class accessor_property_list : protected sycl::detail::PropertyListBase {
// These structures check if compile-time-constant property is present in
// list. For runtime properties this check is always true.
template <class T, class U> struct AreSameTemplate : std::is_same<T, U> {};
template <template <class...> class T, class T1, class T2>
struct AreSameTemplate<T<T1>, T<T2>> : std::true_type {};
#if __cplusplus >= 201703L
template <template <auto...> class T, auto... T1, auto... T2>
struct AreSameTemplate<T<T1...>, T<T2...>> : std::true_type {};
#endif
// This template helps to identify if PropListT parameter pack contains
// property of PropT type, where PropT is a nested instance template of
// compile-time-constant property.
template <typename PropT, typename... PropListT> struct ContainsProperty;
template <typename PropT> struct ContainsProperty<PropT> : std::false_type {};
template <typename PropT, typename Head, typename... Tail>
struct ContainsProperty<PropT, Head, Tail...>
: std::conditional<AreSameTemplate<PropT, Head>::value ||
!sycl::detail::IsCxPropertyInstance<PropT>::value,
std::true_type,
ContainsProperty<PropT, Tail...>>::type {};

// The following structures help to check if two property lists contain the
// same compile-time-constant properties.
template <typename...> struct PropertyContainer {
using Head = void;
using Rest = void;
};
template <typename T, typename... Other>
struct PropertyContainer<T, Other...> {
using Head = T;
using Rest = PropertyContainer<Other...>;
};
template <typename T> struct PropertyContainer<T> {
using Head = T;
using Rest = void;
};

#if __cplusplus >= 201703L
// This template serves the same purpose as ContainsProperty, but operates on
// template template arguments.
template <typename ContainerT, template <auto...> typename PropT,
auto... Args>
struct ContainsPropertyInstance
: std::conditional_t<
!std::is_same_v<typename ContainerT::Head, void> &&
(AreSameTemplate<PropT<Args...>,
typename ContainerT::Head>::value ||
!sycl::detail::IsCxPropertyInstance<
typename ContainerT::Head>::value),
std::true_type,
ContainsPropertyInstance<typename ContainerT::Rest, PropT,
Args...>> {};

template <template <auto...> typename PropT, auto... Args>
struct ContainsPropertyInstance<void, PropT, Args...> : std::false_type {};
#endif

// This template checks if to lists of properties contain the same set of
// compile-time-constant properties in any order.
template <typename ContainerT, typename... OtherProps>
struct ContainsSameProperties
: std::conditional<
ContainsProperty<typename ContainerT::Head, OtherProps...>::value,
ContainsSameProperties<typename ContainerT::Rest, OtherProps...>,
std::false_type>::type {};
template <typename... OtherProps>
struct ContainsSameProperties<void, OtherProps...> : std::true_type {};

#if __cplusplus >= 201703L
// This template helps to extract exact property instance type based on
// template template argument.
template <typename ContainerT, template <auto...> class PropT, auto... Args>
struct GetCxPropertyHelper {
using type = typename std::conditional_t<
AreSameTemplate<typename ContainerT::Head, PropT<Args...>>::value,
typename ContainerT::Head,
typename GetCxPropertyHelper<typename ContainerT::Rest, PropT,
Args...>::type>;
};
template <typename Head, template <auto...> class PropT, auto... Args>
struct GetCxPropertyHelper<PropertyContainer<Head>, PropT, Args...> {
using type = typename std::conditional_t<
AreSameTemplate<Head, PropT<Args...>>::value, Head, void>;
};
#endif

// The structs validate that all objects passed are SYCL properties
template <typename... Tail> struct AllProperties : std::true_type {};
template <typename T, typename... Tail>
struct AllProperties<T, Tail...>
: std::conditional<
std::is_base_of<sycl::detail::DataLessPropertyBase, T>::value ||
std::is_base_of<sycl::detail::PropertyWithDataBase, T>::value ||
sycl::detail::IsCxPropertyInstance<T>::value,
AllProperties<Tail...>, std::false_type>::type {};

accessor_property_list(
std::bitset<sycl::detail::DataLessPropKind::DataLessPropKindSize>
DataLessProps,
std::vector<std::shared_ptr<sycl::detail::PropertyWithDataBase>>
PropsWithData)
: sycl::detail::PropertyListBase(DataLessProps, PropsWithData) {}

public:
template <
typename = typename std::enable_if<AllProperties<PropsT...>::value>::type>
accessor_property_list(PropsT... Props)
: sycl::detail::PropertyListBase(false) {
ctorHelper(Props...);
}

accessor_property_list(const sycl::property_list &Props)
: sycl::detail::PropertyListBase(Props.MDataLessProps,
Props.MPropsWithData) {}

template <typename... OtherProps,
typename = typename std::enable_if<
ContainsSameProperties<PropertyContainer<PropsT...>,
OtherProps...>::value &&
ContainsSameProperties<PropertyContainer<OtherProps...>,
PropsT...>::value>::type>
accessor_property_list(const accessor_property_list<OtherProps...> &OtherList)
: sycl::detail::PropertyListBase(OtherList.MDataLessProps,
OtherList.MPropsWithData) {}

template <typename PropT, typename = typename std::enable_if<
!is_compile_time_property<PropT>::value>::type>
PropT get_property() const {
if (!has_property<PropT>())
throw sycl::invalid_object_error("The property is not found",
PI_INVALID_VALUE);

return get_property_helper<PropT>();
}

template <class PropT>
typename std::enable_if<!is_compile_time_property<PropT>::value, bool>::type
has_property() const {
return has_property_helper<PropT>();
}

#if __cplusplus >= 201703L
template <typename T>
static constexpr
typename std::enable_if_t<is_compile_time_property<T>::value, bool>
has_property() {
return ContainsPropertyInstance<PropertyContainer<PropsT...>,
T::template instance>::value;
}

template <typename T,
typename = typename std::enable_if_t<
is_compile_time_property<T>::value && has_property<T>()>>
static constexpr auto get_property() {
return typename GetCxPropertyHelper<PropertyContainer<PropsT...>,
T::template instance>::type{};
}
#endif

template <typename... OtherPropsT>
static constexpr bool areSameCxProperties() {
return ContainsSameProperties<PropertyContainer<OtherPropsT...>,
PropsT...>::value;
}

private:
template <typename... OtherProps> friend class accessor_property_list;

friend class sycl::property_list;
};
} // namespace ONEAPI
} // namespace sycl
} // __SYCL_INLINE_NAMESPACE(cl)
7 changes: 4 additions & 3 deletions sycl/include/CL/sycl/ONEAPI/atomic_accessor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@ template <typename DataT, int Dimensions, memory_order DefaultOrder,
access::placeholder IsPlaceholder = access::placeholder::false_t>
class atomic_accessor
: public accessor<DataT, Dimensions, access::mode::read_write, AccessTarget,
IsPlaceholder> {
IsPlaceholder, ONEAPI::accessor_property_list<>> {

using AccessorT = accessor<DataT, Dimensions, access::mode::read_write,
AccessTarget, IsPlaceholder>;
using AccessorT =
accessor<DataT, Dimensions, access::mode::read_write, AccessTarget,
IsPlaceholder, ONEAPI::accessor_property_list<>>;

private:
using AccessorT::getLinearIndex;
Expand Down
6 changes: 4 additions & 2 deletions sycl/include/CL/sycl/ONEAPI/reduction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#pragma once

#include "CL/sycl/ONEAPI/accessor_property_list.hpp"
#include <CL/sycl/ONEAPI/group_algorithm.hpp>
#include <CL/sycl/accessor.hpp>
#include <CL/sycl/handler.hpp>
Expand Down Expand Up @@ -349,10 +350,11 @@ class reduction_impl {
using result_type = T;
using binary_operation = BinaryOperation;
using accessor_type =
accessor<T, Dims, AccMode, access::target::global_buffer, IsPlaceholder>;
accessor<T, Dims, AccMode, access::target::global_buffer, IsPlaceholder,
ONEAPI::accessor_property_list<>>;
using rw_accessor_type =
accessor<T, Dims, access::mode::read_write, access::target::global_buffer,
IsPlaceholder>;
IsPlaceholder, ONEAPI::accessor_property_list<>>;
static constexpr access::mode accessor_mode = AccMode;
static constexpr int accessor_dim = Dims;
static constexpr int buffer_dim = (Dims == 0) ? 1 : Dims;
Expand Down
Loading