-
Notifications
You must be signed in to change notification settings - Fork 67
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
Clarify the builtin functions (again) #440
Conversation
After gaining some implementation experience, we decided to change the clarification of the builtin functions. Our previous attempt in #428 added many overloads, and we discovered that this increased the time it takes to compile the <sycl/sycl.hpp> header. After further reflection, we decided that a different mix of overloads vs. templates was more consistent with C++ and it also results in better compile times. In general, we follow C++ whenever there is a precedent. For example, the math functions like `fmax` and `isinf` have separate overloads for scalar inputs because C++ defines these same function in that way. However, we use template parameters for the variants that take `marray` or `vec` because there is no C++ precedent here. Other functions like `clamp` have a C++ precedent where scalar arguments are template parameters, so SYCL follows suit here also. Of course, there are many cases where there is no C++ precedent. In these cases, SYCL tries to be self consistent. For example, the relational functions like `isequal` have separate overloads for scalar inputs to be consistent with `isinf` and the other math functions. We also felt that the "generic type names" were adding confusion to the spec. Therefore, this commit remove all these generic pseudo-type definitions and shows the exact synopsis for each builtin function. This was hard to do with the old table format, so the tables defining the builtin functions have been completely rewritten to match the style used by the newer builtin functions (e.g. the group functions). This style leaves more horizontal space for the synopsis, which makes it easier to write the synopsis without awkward line breaks. The "Constraints" section of this style also makes it easier to describe the constraints for the various template parameters. Some other changes of note: * The Common Functions were inconsistently specified for the `half` type. We had defined some `half` overloads, but we missed others. This commit adds `half` support consistently to these functions. * The introductory paragraphs have been modified to remove general statements about the types that are supported by the functions. These statements were sometime in conflict with the actual function definitions, and it seemed better to avoid redundancy. Each function clearly specifies the allowed input types, so we do not need to say this again in the introduction. * The "native precision" and "half precision" math functions have been split out into their own sub-sections. It was easy to miss these functions before because they came after a long table of regular math functions. It's now much easier to see that they exist. * All uses of "latexmath" have been removed from the descriptions of the builtin functions and replaced with Asciidoc formatting. This results in a more consistent style, and it also fixed several problems where the latexmath version was not rendered correctly in the final PDF and/or HTML documents. Closes internal issue 278 (again). Closes #321
Add a new type alias `value_type` to `vec`, making it more consistent with `marray`. This makes it much easier to define the templated versions of the builtin functions because we can rely on this type alias for both `vec` and `marray`.
Remove the old tables defining the builtin functions. We no longer need the section defining the generic pseudo-type names, so remove it too. Note that this changes the section numbering for all the builtin functions!
Since we removed the generic pseudo-types, we can also remove the rouge formatting support for them.
b07970b
to
4437aa9
Compare
Currently the host-side implementation of sycl::nextafter with sycl::half uses the float variant of std::nextafter. However, due to the conversion between half and float, the result may be unexpected. Likewise, KhronosGroup/SYCL-Docs#440 removes the reference to single-precision floating point results. Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
Currently the host-side implementation of sycl::nextafter with sycl::half uses the float variant of std::nextafter. However, due to the conversion between half and float, the result may be unexpected. Likewise, KhronosGroup/SYCL-Docs#440 removes the reference to single-precision floating point results. Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
Restore some wording in `nextafter` to be the same as it was before this PR. That wording is incorrect, but I want to break this fix out into a separate PR to highlight the change.
We don't define the Words of Power (Constraints, Mandates, etc.). We should using the definitions at [structure.specifications#3]. That way there is no question on it being enforced via SFINAE/ Slide 6: As I mentioned, I prefer getting rid of the obvious As I learned in LWG on Wednesday, Slide 10: The difference between templated functions and overloads is that overloads automatically allow implicit conversions. If we had struct MyInt {
operator int() const { /* ... */ }
/* ... */
}; It wouldn't work. (I'm just pointing this out. I'm not sure which way we should go.) (I'm out of time for today...) |
Address review feedback. Remove uses of `typename` that are obvious to human readers.
Thanks @nliber for the review:
I agree that it would be good to define these terms, but we should do it in a separate PR. The SYCL spec used these structural words even before my PR, so this is not something new that I added here. I opened internal issue 664 to capture this, and I'm happy to draft something once the WG agrees to a direction.
I did this in 817fe7d.
Given that definition, I think |
This is definitely an interesting case, which is why I wanted to highlight it in my slides. In some sense, this is a tradeoff between consistency with C++ vs. consistency with the other SYCL integer functions. I think there are a few reasonable options:
I have a weak preference for 1 over 3, and I have a stronger dislike of 2 because of the API break relative to previous SYCL releases. Whatever we choose, I think we should do the same thing for |
I have a preference to solution 3 since I imagine that an ML engineer writing generic SYCL code for a ReLU and use it on an |
Both option 1 and option 3 behave this way. Do you have a reason to prefer option 3 over option 1? Option 1 is what I have in this PR now. I have a weak preference for this option mainly because it retains consistency with all the other SYCL integer functions. As a reminder, option 1 defines
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First of all, thank you for putting this together, this is a lot of effort and I think it will really improve the clarity of the specification. Apologies it took me so long to review this, I've been reviewing it bit by bit over the past couple of weeks.
I think overall this looks great, I much prefer the horizontal wording format.
My main suggestion would prefer if possible, to avoid having the return type of builtins defined as /*return type*/
and instead have a type trait, I think this makes it clearer what type is returned and avoids having to describe it in the wording. One issue with this is inferring type information of a __swizzled_vec__
argument, but I think with a few type traits this could also work.
I also noticed that there is some wording that is repeated a lot for common function patterns but I'm wary of suggesting a simplification as I feel it would sacrifice readability.
On the question of overloads vs templates, I think I would lean towards option 1, as option 2 removes functionality and option 3 has an inconsistency which I worry would be confusing. Though I think there's a fourth option; have scalar overloads for signed and unsigned integer types, and keep the template function for marray
/vec
, this way user-defined conversions work, it would align with C++ for the functions that it defines and follows the same principal for the ones it doesn't, all scalar overloads would be consistent, and this would also be consistent with the floating point builtins.
Hi @AerialMantis, Thanks for reviewing this PR. I'd like to dig into this comment of yours because I'm not sure what you are proposing:
I assume you are proposing a 4th option for the definition of
(I.e. the same as option 3, but adding overloads for Or, are you suggesting adding overloads for all scalar types like:
Either way, doesn't this have the same inconsistency that you point out for option 3? The other "integer" functions in SYCL do not have all these overloads. For example,
I considered adding overloads for all 11 scalar integer types for all the "integer" functions in SYCL, however this would make SYCL inconsistent with C++. C++ defines |
Address code review comment. Remove this introductory text describing the return value for the relational functions. This is redundant now because the function descriptions clearly describe the return value.
Address code review comment. The `__swizzled_vec__` type does not have any specified template parameters, so do use it in a context that requires template parameters.
I had an AR to research precedents for the
Here, cppreference uses the comment The C++ specification, however, uses italic font. For example, see the definition of
Of the two, l actually prefer the comment style because I find that it stands out better visually. The italic font is more subtle, so it's easy to miss if you read quickly. There is also a practical reason to prefer the comment style. The Aciidoctor toolchain makes it difficult to use italic font in source code blocks. I can get it to mostly work for the HTML render (with some minor degradation of the syntax highlighting). However, I cannot get it to work with the PDF render. If this were the only option, we could look into ways to work-around or fix the PDF render bug. However, it seems easier to use the comment style, and I prefer the way that style looks anyway. |
Searching through the standard for an example, we have in [memory.syn] the following declaration: template<class Ptr>
constexpr auto to_address(const Ptr& p) noexcept; and in [pointer.conversion], the verbiage: Returns: We also could just use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still need some time to dive into the discussions.
@@ -180,76 +180,6 @@ class Sycl < Cpp | |||
wait_and_throw | |||
) | |||
|
|||
# Generic types used in SYCL pseudo code descriptions like Gen, | |||
# SGen, GenVec... | |||
sycl_generic_types = %w( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest keeping this but empty, as this infrastructure could be used in the future instead of diving again into which Rouge feature we could use for a new kind of keywords in SYCL Next.
For example if we introduce some concept
in SYCL Next.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I restored the rouge support in 904fb54.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious : where is this commit gone?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, thanks for noticing this! I forgot to push that commit to the branch corresponding to this PR. It should be there now.
The branches are a little complicated with all these stacked PRs.
If we were not stuck in C++17... |
Correct a mistake in this PR. The `any` and `all` functions (for `vec` inputs) should return 1 for true, not -1. This is consistent with the SYCL spec before this PR, and it is consistent with OpenCL.
@nliber rereading this I am unsure I understand which template<class Ptr>
constexpr auto to_address(const Ptr& p) noexcept; or C++20 constexpr auto to_address(const auto& p) noexcept; ? |
At the end, I wonder whether a 5th option with just template <typename Anything>
auto abs(Anything x); with implementation specialized for any type discussed here in the SYCL spec + any other type which are implicitly convertible to the types already handled in the SYC spec would not just work™. |
If this is where we want to go eventually, we should choose option 1 (i.e. the option already in this PR). Remember, this is a bug fix to SYCL 2020, so it's not the time to expand the scope of these functions. If we choose option 1 now, we can simply relax the constraints later, which gets us to your option 5. |
I assume @nliber meant the C++11 To be honest, my preference is still to use the |
fa63259
to
84c9896
Compare
Rather than deleting the rouge support for the "gentype" pseudo-types completely, retain the support but leave it as an empty placeholder that we can use in the future. For example, we might use this to add syntax coloring for concept names (if we add any).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Massive!
[This comment](KhronosGroup#440 (comment)) in KhronosGroup#440 noted that the number of elements in a `__swizzled_vec__` is not clearly defined. Clarify this and also clarify that the member functions operate on the result of the swizzle operation.
Currently the host-side implementation of sycl::nextafter with sycl::half uses the float variant of std::nextafter. However, due to the conversion between half and float, the result may be unexpected. Likewise, KhronosGroup/SYCL-Docs#440 removes the reference to single-precision floating point results. Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
After gaining some implementation experience, we decided to change the
clarification of the builtin functions. Our previous attempt in #428
added many overloads, and we discovered that this increased the time it
takes to compile the <sycl/sycl.hpp> header. After further reflection,
we decided that a different mix of overloads vs. templates was more
consistent with C++ and it also results in better compile times.
In general, we follow C++ whenever there is a precedent. For example,
the math functions like
fmax
andisinf
have separate overloads forscalar inputs because C++ defines these same function in that way.
However, we use template parameters for the variants that take
marray
or
vec
because there is no C++ precedent here. Other functionslike
clamp
have a C++ precedent where scalar arguments are templateparameters, so SYCL follows suit here also.
Of course, there are many cases where there is no C++ precedent. In
these cases, SYCL tries to be self consistent. For example, the
relational functions like
isequal
have separate overloads for scalarinputs to be consistent with
isinf
and the other math functions.We also felt that the "generic type names" were adding confusion to
the spec. Therefore, this commit remove all these generic pseudo-type
definitions and shows the exact synopsis for each builtin function.
This was hard to do with the old table format, so the tables defining
the builtin functions have been completely rewritten to match the
style used by the newer builtin functions (e.g. the group functions).
This style leaves more horizontal space for the synopsis, which makes
it easier to write the synopsis without awkward line breaks. The
"Constraints" section of this style also makes it easier to describe
the constraints for the various template parameters.
Some other changes of note:
This PR also adds the member type alias
value_type
tovec
, makingit more consistent with
marray
. This makes it much easier to definethe templated versions of the builtin functions because we can rely on
this type alias for both
vec
andmarray
.The Common Functions were inconsistently specified for the
half
type. We had defined some
half
overloads, but we missed others.This commit adds
half
support consistently to these functions.The introductory paragraphs have been modified to remove general
statements about the types that are supported by the functions.
These statements were sometime in conflict with the actual function
definitions, and it seemed better to avoid redundancy. Each function
clearly specifies the allowed input types, so we do not need to say
this again in the introduction.
The "native precision" and "half precision" math functions have been
split out into their own sub-sections. It was easy to miss these
functions before because they came after a long table of regular math
functions. It's now much easier to see that they exist.
All uses of "latexmath" have been removed from the descriptions of
the builtin functions and replaced with Asciidoc formatting. This
results in a more consistent style, and it also fixed several
problems where the latexmath version was not rendered correctly in
the final PDF and/or HTML documents.
Note that this PR changes the section numbering for many of the
sections that define builtin functions. This is because the
section defining the "generic" pseudo-types no longer exists and
because there are new sections for the native-precision and half-
precision math functions.
Closes internal issue 278 (again).
Closes #321