Skip to content

Latest commit

 

History

History
681 lines (523 loc) · 28 KB

sycl_ext_oneapi_properties.asciidoc

File metadata and controls

681 lines (523 loc) · 28 KB

sycl_ext_oneapi_properties

1. Introduction

The sycl::property_list found in SYCL 2020 is used to store properties used in the construction of runtime classes. It does so in a fully dynamic manner, such that it is not possible to obtain any useful information about the types of properties passed nor their values at compile time.

Compile-time-constant properties are an important building block for classes and functions that have a need to propagate compile-time information for semantic and optimization purposes, while runtime properties continue to serve an important role in dynamic parameter specification.

This extension introduces sycl::ext::oneapi::experimental::properties, which is a replacement for sycl::property_list that supports the storage and manipulation of compile-time-constant properties in addition to runtime properties.

2. Contributors

Joe Garvey, Intel
Roland Schulz, Intel
Ilya Burylov, Intel
Michael Kinsner, Intel
John Pennycook, Intel
Jessica Davies, Intel
Greg Lueck, Intel
Jason Sewall, Intel

3. Notice

Copyright (c) 2021 Intel Corporation. All rights reserved.

4. Status

This is an experimental extension specification, intended to provide early access to features and gather community feedback. Interfaces defined in this specification are implemented in DPC++, but they are not finalized and may change incompatibly in future versions of DPC++ without prior notice. Shipping software products should not rely on APIs defined in this specification.

5. Version

Last Modified Date: 2021-12-15
Revision: 2

6. Dependencies

This extension is written against the SYCL 2020 Specification (revision 3).

7. Overview

The purpose of this document is to clearly describe and specify a new property list (properties) and related concepts, types, and mechanisms, and to give examples and context for their usage.

7.1. Motivation

sycl::property_list enables users to pass additional parameters when constructing objects of the runtime classes, but the design of sycl::property_list is such that it is not possible to reliably determine the contents of these passed parameters at compile time.

There are numerous circumstances where parameters are only useful when their presence and contents are known at compile-time; this extension addresses this by introducing a properties class that is able to represent compile-time-constant properties in addition to runtime properties.

The handling of runtime properties in properties departs from that of sycl::property_list by having the types of any runtime properties present be known at compile-time. The distinction between runtime properties and compile-time-constant properties is that runtime properties store values that are set at runtime.

7.2. Examples

Note

Due to type deduction, users should usually not need to specify the template parameters of properties directly. In cases the type is needed, decltype should be used.

A property list that has the compile-time constant property foo can be created as follows:

properties P1{foo};

where foo is a global variable representing a property value of the compile-time constant property.

The type of a properties object is determined by the set of runtime properties and compile- time-constant property values that it contains. In the following examples, bar and baz are compile-time-constant properties, while foo is a runtime property.

properties P1{bar};
properties P2{bar, foo{argv[0]}};
properties P3{bar, baz};
properties P4{baz, bar};
static_assert(!std::is_same_v<decltype(P1), decltype(P2)>); // P1 and P2 contain different properties
static_assert(!std::is_same_v<decltype(P1), decltype(P3)>); // P1 and P3 contain different properties
static_assert(std::is_same_v<decltype(P3), decltype(P4)>); // The order properties are specified doesn't change the type

7.3. Goals

The goals of this extension are:

  1. Enable the storage, manipulation, and propagation of both compile-time-constant properties and runtime properties via properties

  2. Handle runtime properties such that the existence and types of runtime properties in a property list are known at compile time (while keeping their values dynamic).

The intention is to provide a robust mechanism with which to pass compile-time-constant properties and runtime properties to classes and functions.

7.4. Glossary

property

A property is represented by a key and value. Properties can be used to provide extra values to classes or functions.

property value

An object of the property value class. A property value has zero or more property parameters. For runtime properties the value type is the same as the key type. For compile time properties the value type is given by the value_t type alias of the key type.

property key

A class representing the property key. It is used to query properties.

property parameter

A parameter of a property that can be set and queried. May be dynamic (runtime) or compile-time-only, depending on the property. For compile-time-constant properties, property parameters may be types or non-types. For runtime properties, property parameters must be non-types.

runtime property

A property that has property parameters determined at runtime and stored as members of the property.

compile-time-constant property

A property that has no parameters that are determined at runtime. This includes properties that have no parameters and properties where all parameters are determined at compile time. If such a property has parameters, their values are stored as template arguments of the property value class.

8. Proposal

8.1. Feature test macro

This extension provides a feature-test macro as described in the core SYCL specification section 6.3.3 "Feature test macros". An implementation supporting this extension must predefine the macro SYCL_EXT_ONEAPI_PROPERTIES to one of the values defined in the table below. Applications can test for the existence of this macro to determine if the implementation supports this feature, or applications can test the macro’s value to determine which of the extension’s APIs the implementation supports.

Value Description

1

Initial extension version. Base features are supported.

8.2. Representation of Properties

Properties have a value and key type, and by convention, these classes are declared in the root of the sycl::ext::oneapi::experimental namespace. For a runtime property the key and value types are the same and the name of the property value class has no suffix. A runtime property value typically has a constructor which takes the value(s) of the properties and member function(s) which return those values.

namespace sycl::ext::oneapi::experimental {

// This is a runtime property value with one integer parameter.
// The name of the property value class is the the name of the property without any suffix.
struct foo {
  foo(int);
  int value;
};
// A runtime property key is an alias to the value type.
using foo_key = foo;

} // namespace experimental::oneapi::ext::sycl

For compile-time constant parameters the value type is a template specialization of property_value. The property key class contains a value_t alias which is templated on the property parameters. The property_value class holds the values of the compile-time parameters as template arguments. The parameters to a compile- time-constant property can be either types or non-type values. The implementation provides a variable with the property value type. The variable has the name of the property without a suffix.

namespace sycl::ext::oneapi::experimental {

template<typename...> struct property_value;

// This property has no parameters.
struct bar_key {
  using value_t = property_value<bar_key>;
};
// bar is an object of the property value type of bar.
inline constexpr bar_key::value_t bar;

// This property has one integer non-type parameter.
struct baz_key {
  template<int K>
  using value_t = property_value<baz_key, std::integral_constant<int, K> >;
  // Note: integral_constant is used for the example. An implementation can use a different mapping.
};
// baz is an object of a property value type of baz.
template<int K>
inline constexpr baz_key::value_t<K> baz;

// This property has an arbitrary number of type parameters.
struct boo_key {
  template<typename...Ts>
  using value_t = property_value<boo_key, Ts...>;
};
// boo is an object of a property value type of boo.
template<typename... Ts>
inline constexpr boo_key::value_t<Ts...> boo;

} // namespace experimental::oneapi::ext::sycl

8.3. Property traits

All runtime and compile-time-constant properties must have a specialization of is_property_key and is_property_value that inherits from std::true_type, and they must have a specialization of is_property_key_of and is_property_value_of that inherits from std::true_type for each SYCL runtime class that the property can be applied to. All have a base case which inherits from std::false_type.

namespace sycl::ext::oneapi::experimental {
//Base case
template<typename> struct is_property_key : std::false_type {};
template<typename, typename> struct is_property_key_of : std::false_type {};

template<> struct is_property_key<foo_key> : std::true_type {};
template<> struct is_property_key<bar_key> : std::true_type {};

// These properties can be applied to any SYCL object.
template<typename SyclObjectT>
struct is_property_key_of<foo_key, SyclObjectT> : std::true_type {};
template<typename SyclObjectT>
struct is_property_key_of<bar_key, SyclObjectT> : std::true_type {};

// is_property_value and is_property_value_of based on is_property_key(_of)
template<typename V, typename=void> struct is_property_value;
template<typename V, typename O, typename=void> struct is_property_value_of;
// Specialization for runtime properties
template<typename V> struct is_property_value<V, std::enable_if_t<(sizeof(V)>0)>> : is_property_key<V> {};
template<typename V, typename O> struct is_property_value_of<V, O, std::enable_if_t<(sizeof(V)>0)>> : is_property_key_of<V,O> {};
// Specialization for compile-time-constant properties
template<typename V> struct is_property_value<V, std::void_t<typename V::key_t>> :
  is_property_key<typename V::key_t> {};
template<typename V, typename O> struct is_property_value_of<V, O, std::void_t<typename V::key_t>> :
  is_property_key_of<typename V::key_t, O> {};

} // namespace experimental::oneapi::ext::sycl

8.4. Property value class

The property_value class has implementation-defined template parameters. In the common case when the property has a single parameter, it provides a member variable named value and a type alias named value_t to retrieve the value and type of the parameter. When a property has more than one parameter, the property_value class provides more semantically meaningful ways to retrieve the values and types of the parameters.

namespace sycl::ext::oneapi::experimental {

template<typename Property, typename First, typename...Others>
struct property_value {
  // Alias of the property key type
  using key_t = Property;

  // Each property with multi-parameter property_value must define template
  // specializations for accessing the parameters.

  // Available only when the property value has a single parameter and `value_t` of the property takes a non-type parameter
  static constexpr auto value = First::value;

  // Available only when the property value has a single parameter
  using value_t = First;
};

} // namespace experimental::oneapi::ext::sycl

The members of property_value are described in the table below.

Member Description
static constexpr auto value = First::value;

The value of the parameter. Available only when there is exactly one non-type parameter.

using value_t = First;

Available only when there is exactly one parameter. When the parameter’s value is a type, value_t is that type. When the parameter’s value is a non-type, value_t is an implementation-defined type with a member constant value equal to the value.

using key_t = property;

The property key type.

8.5. Property operators

The implementation provides equality and inequality operators for properties.

namespace sycl::ext::oneapi::experimental {

// Available only if Prop is a compile-time constant property
template <typename Prop, typename...A, typename...B>
constexpr bool operator==(property_value<Prop, A...> V1, property_value<Prop, B...> V2);

// Available only if Prop is a compile-time constant property
template <typename Prop, typename...A, typename...B>
constexpr bool operator!=(property_value<Prop, A...> V1, property_value<Prop, B...> V2);

// Available only if Prop is a runtime property
template <typename Prop>
bool operator==(Prop P1, Prop P2);

// Available only if Prop is a runtime property
template <typename Prop>
bool operator!=(Prop P1, Prop P2);

} // namespace experimental::oneapi::ext::sycl
Function Description
template <typename Prop, typename...A, typename...B>
constexpr bool operator==(property_value<Prop, A...> V1, property_value<Prop, B...> V2);

Returns true if V1 and V2 have the same type. Returns false otherwise.

template <typename Prop, typename...A, typename...B>
constexpr bool operator!=(property_value<Prop, A...> V1, property_value<Prop, B...> V2);

Returns false if V1 and V2 have the same type, true otherwise.

template <typename Prop>
bool operator==(Prop P1, Prop P2);

Returns true if all parameters (=member variables) of P1 and P2 are the same. Returns false otherwise.

template <typename Prop>
bool operator!=(Prop P1, Prop P2);

Returns false if all parameters of P1 and P2 are the same. Returns true otherwise.

8.6. Property list properties

This extension adds a new template class, sycl::ext::oneapi::experimental::properties, which is a property list that can contain compile-time constant properties as well as runtime properties.

properties is a class template, and the properties stored by it influence its type. Two properties objects have the same type if and only if they were constructed with the same set of compile-time constant property values and the same set of runtime properties.

Note

The runtime properties contained in the property list affect the type of sycl::ext::oneapi::experimental::properties, but their property values do not.

It is possible at compile-time to determine whether a properties object contains a particular (runtime or compile-time constant) property. See the static constexpr function has_property of the properties class.

It is possible at compile-time to determine the property value of a compile-time constant property contained in a properties object. See the static constexpr function get_property of the properties class.

The get_property member function of properties returns a property value object. For runtime properties, the get_property member function of properties returns a copy of the property object passed to the properties constructor.

In the same way that two different runtime properties of the same type cannot be applied to the same object, two compile-time constant property values of the same property class T cannot belong to the same properties, whether the property value is the same or different.

Note

That last sentence is not explicitly stated in the core SYCL spec, but it is assumed by the properties interface.

The empty_properties_t type alias is a shorthand for the type of an empty property list.

The new properties class template is as follows:

namespace sycl::ext::oneapi::experimental {

template<typename PropertyValuesT>
class properties {
  // static_assert: all types in PropertyValuesT need to be properties and need to be unique and sorted.
 public:
  // props can contain objects of compile-time constant and runtime property values in any order.
  // Available only if all types in PropertyValueTs are property values.
  // Only valid if all types in PropertyValueTs are in PropertyValuesT,
  // and all types in PropertyValuesT  which are not default constructible are in PropertyValueTs.
  template<typename... PropertyValueTs>
  constexpr properties(PropertyValueTs... props);

  template<typename PropertyKeyT>
  static constexpr bool has_property();

  // Available only when PropertyT is the property class of a runtime property
  template<typename PropertyT>
  constexpr PropertyT get_property() const;

  // Available only when PropertyKeyT is the property class of a compile-time constant property
  template<typename PropertyKeyT>
  static constexpr auto get_property();
};

using empty_properties_t = decltype(properties{});

} // namespace experimental::oneapi::ext::sycl
Note

Implementations will need a deduction guide to satisfy the requirement that properties objects created from the same set of compile-time constant property values and runtime properties must have an identical type. The requirement that properties objects have the same type if they contain the same set of compile-time constant property values and runtime properties also implies that implementations must define an ordering over all properties. This extension provides no mechanism for users to define their own properties.

The following table describes the constructors of the properties class:

Constructor Description
template<typename ... PropertyValueTs>
constexpr properties(PropertyValueTs... props);

Available only when each argument in props is an object of a property value. Construct a property list with zero or more property values. This constructor can accept both runtime and compile-time constant property values. Each property in the property list (as determined by PropertyValuesT) that is not default constructable must have an object provided in props.

The following table describes the member functions of the properties class:

Member function Description
template<typename PropertyKeyT>
static constexpr bool has_property();

Returns true if the property list contains the property with property key class PropertyKeyT. Returns false if it does not. Available only when PropertyKeyT is a property key class.

template<typename PropertyT>
PropertyT get_property() const;

Returns a copy of the property value contained in the property list. Available only if PropertyT is a runtime property and the property list contains a PropertyT property.

template<typename PropertyKeyT>
static constexpr auto get_property();

Returns a copy of the property value contained in the property list. Available only if PropertyKeyT is the property key class of a compile-time constant property and the property list contains a property with the PropertyKeyT key.

The following trait is added to recognize a properties.

namespace sycl::ext::oneapi::experimental {

// New trait to recognize a properties
template<typename propertyListT>
struct is_property_list;

template<typename propertyListT>
inline constexpr bool is_property_list_v = is_property_list<properties>::value;

} // namespace experimental::oneapi::ext::sycl

The following table describes the new is_property_list trait:

Traits Description
template<typename propertyListT>
struct is_property_list;

An explicit specialization of is_property_list that inherits from std::true_type must be provided for each specialization of properties. All other specializations of is_property_list must inherit from std::false_type.

template<typename propertyListT>
inline constexpr bool is_property_list_v;

Variable containing value of is_property_list<propertyListT>::value.

8.7. Type of properties

The details of the properties template argument(s) are unspecified. In particular the sorting order of properties is unspecified. The type of the property list can be written with decltype.

The following example shows how decltype is used to create a property list type containing the compile-time constant properties bar and baz:

using P1 = decltype(properties(baz<1>, bar));
using P2 = decltype(properties(bar, baz<1>));
static_assert(std::is_same<P1, P2>::value); // Succeeds, since the order of properties does not matter
static_assert(P1::get_property<baz_key>().value == 1);

8.8. Querying Properties in Device Code

All values of compile-time constant properties are device copyable.

Some runtime properties may not be device copyable. A properties object is device copyable if and only if it contains no runtime properties that are not device copyable. A device copyable properties object can be passed as a kernel parameter (as defined in the SYCL specification section 4.12.4).

In the following examples, foo is a compile-time constant property and is therefore device copyable. The property bar is a runtime property that is also device copyable.

static_assert(sycl::is_device_copyable_v<decltype(foo<1>)>);
static_assert(sycl::is_device_copyable_v<bar>);

properties P1{foo<1>, bar{}};

// All properties in P1 are device copyable, so P1 is device copyable
static_assert(sycl::is_device_copyable_v<decltype(P1)>);

h.single_task([=] {
  auto a = P1.has_property<foo_key>(); // OK
  auto b = P1.get_property<foo_key>(); // OK
  auto c = P1.has_property<bar_key>(); // OK
  auto d = P1.get_property<bar_key>(); // OK
});

A properties object that contains a runtime property that is not device copyable can not be passed as a kernel parameter. However, a kernel can still call the static constexpr member functions by using decltype, as shown in the example below. This allows a kernel to query for the existence of any property in a properties object, and it allows a kernel to query the value of a compile-time constant property, but it does not allow the kernel to query the value of a (device copyable or not device copyable) runtime property. The following decltype syntax must be used to avoid capturing the not device copyable properties object.

In the following example, foo is a compile-time constant property and property bar_vec is a runtime property that is not device copyable.

// P2 contains the runtime property bar_vec, which is not device copyable
// P2 can not be a kernel parameter. P2 is not device copyable.
// decltype must be used even for compile-time constant properties
static_assert(!sycl::is_device_copyable_v<bar_vec>);
std::vector<int> v(atoi(argv[1]), 42);
properties P2{foo<1>, bar_vec{v}};
static_assert(!sycl::is_device_copyable_v<decltype(P2)>);
h.single_task([=] {
  auto a = decltype(P2)::has_property<foo_key>(); // OK, since decltype is used
  auto b = P2.has_property<foo_key>(); // incorrect, since decltype is missing

  auto c = decltype(P2)::has_property<bar_vec_key>(); // OK, since decltype is used
  auto d = decltype(P2)::get_property<bar_vec_key>(); // incorrect, since bar_vec is a runtime property

  auto e = decltype(P2)::get_property<foo_key>(); // OK, since foo is a compile-time constant property
  auto f = P2.get_property<foo_key>(); // incorrect, since decltype is missing
});

9. Extended Examples

The arguments passed to the constructor of a runtime property specify the value of the property’s parameters at runtime. Similarly, compile-time constant properties may have parameters that affect their semantics. For example, the property foo takes a single integer parameter:

properties P5{foo<1>};
properties P6{foo<2>};
properties P7{foo<1>, bar};
static_assert(P6.has_property<foo_key>()); // No need to specify the value of the property's parameter
static_assert(!std::is_same_v<decltype(P5), decltype(P6)>); // The parameter values of foo are different
auto f1 = P5.get_property<foo_key>(); // f1 is a copy of global variable foo<1 >
auto f2 = P6.get_property<foo_key>(); // f2 is a copy of global variable foo<2 >
static_assert(f1 != f2); // Not equal since the property values are different, i.e., 1 vs. 2
auto f3 = P7.get_property<foo_key>();
static_assert(f3 == f1); // Equal because the property values are the same, i.e., equal to 1

The parameters of a property may also be types. For example, the property foo_types takes an arbitrary number of parameters, each of which is a type. In this example, foo_types exposes its parameters (which are types) as first_t, second_t, third_t.

properties P8{foo_types<float, int, bool>};
using f = decltype(P8.get_property<foo_types_key>());
using t1 = f::first_t;
using t2 = f::second_t;
using t3 = f::third_t;
static_assert(std::is_same_v<t1, float);
static_assert(std::is_same_v<t2, int>);
static_assert(std::is_same_v<t3, bool>);
Note

Properties should provide semantically meaningful functions to access the parameters' values.

For functions that take a property list parameter, it is possible to restrict the parameter to require a specific property. If the property takes a compile-time constant parameter, it is further possible to restrict the function to take a property list that has a property with a specific parameter. The following example demonstrates this, where foo is runtime property and bar is a compile-time constant property.

template<typename PropertiesT>
std::enable_if_t<is_property_list_v<PropertiesT>> my_func1(propertyListT p);

template<typename PropertiesT>
std::enable_if_t<is_property_list_v<PropertiesT> && propertyListT::template has_property<foo_key>()> my_func2(PropertiesT p);

template<typename PropertiesT>
std::enable_if_t<is_property_list_v<PropertiesT> && (propertyListT::template get_property<bar_key>().value == 2)> my_func3(PropertiesT p);
...
my_func1(properties{foo}); // Legal.  my_func1 accepts any properties
my_func2(properties{foo}); // Legal.  my_func2 requires foo
my_func2(properties{bar}); // Illegal.  my_func2 requires foo
my_func2(properties{foo, bar<1>}); // Legal.  Other properties can also be specified.
my_func3(properties{bar<2>); // Legal. my_func3 requires bar with value 2
my_func3(properties{bar<1>); // Illegal. my_func3 requires bar with value 2

In the examples above, also note the distinction between the property key class foo_key and the property value variable foo, both associated with property foo. Note how the property value variable foo is used to create the property list, while property key class foo_key is used to query the property list.

10. End Matter

This section provides more detailed information for implementers. It is non-normative, and may be removed in future revisions of the extension.

10.1. Interface Guidelines for properties consumers

Adding a new compile-time constant property requires implementers to introduce the following:

  • A new class representing the property key

  • Specializations of sycl::is_property_key and sycl::is_property_key_of for the new property class

  • A global variable that represents an object of the property value

10.2. Example of a Compile-time Constant Property

This is an example showing the definition of a compile-time constant property foo that takes a single integer parameter. The property key class associated with the property is foo_key.

namespace sycl::ext::oneapi::experimental {

// foo is the property key class
struct foo_key {
  template<int K>
  using value_t = property_value<foo, std::integral_constant<int, K>>;
};

// foo is a variable of the property value class that can be used to construct a
// property list with this property
template<int K>
inline constexpr foo::value_t<K> foo;

// foo is a property
template<>
struct is_property_key<foo_key> : std::true_type {};

// foo can be applied to any object
template<typename SyclObjectT>
struct is_property_key_of<foo_key, SyclObjectT> : std::true_type {};

} // namespace experimental::oneapi::ext::sycl

11. Revision History

Rev Date Author Changes

2

2021-12-15

Roland Schulz

Rename of value/key

1

2021-07-13

Jason Sewall

Initial internal draft