-
Notifications
You must be signed in to change notification settings - Fork 739
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
[SYCL] Emit a warning on constexprs captured in SYCL kernels #2824
[SYCL] Emit a warning on constexprs captured in SYCL kernels #2824
Conversation
clang format fails for |
@bader The test failures reported are all related to sycl-post-link tool in I verified the tests locally and they all pass. Could you clarify if this a buildbot related issue? |
@AlexeySachkov , could you please take a look? Can it be caused by e481174 ? |
Sure, I will take a look. It seems like pulldown has landed before my PR got merged, but after I had launched pre-commit: there was a change in typed attributes for function arguments, I just need to re-generate LLVM IR for those tests |
Should be fixed by #2846 |
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.
Thanks!
@bader This is ready to be merged. |
It sounds like the compiler drops |
Compiler captures a |
The warning generated is only for implicit captures. Since the address of the constexpr variable is taken, it gets turned into a kernel parameter. Otherwise, it remains constexpr. @erichkeane says that this could potentially be addressed in the library with overloads (and that it would be difficult to do so), but I didn't quite follow that thought. |
h.single_task<LambdaKernel>( | ||
[=]() { | ||
// constexpr 'OdrUsedVar' is odr-used here. | ||
const unsigned *ptr = &OdrUsedVar; // expected-warning {{captured constexpr 'OdrUsedVar' will be a kernel argument in device code}} |
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 don't quite get the purpose of this warning.
I think in order to understand this warning message, user must know DPC++ implementation details about lowering lambda object into kernel function and how kernel function parameters are composed. Do you think it's clear for DPC++ users?
Another point it's generic C++ behavior and not SYCL specific issue:
template <typename T>
void foo(T t) {t();}
// ...
foo([=]() { const unsigned *ptr = &OdrUsedVar; }); // OdrUsedVar is captured and might cause performance issues
foo([=]() { unsigned x = 10 + OdrUsedVar; }); // OdrUsedVar is not captured. No performance issues?
Should we emit similar warning for any lambda expression?
It's probably more useful to implement such diagnostics in performance profiler because passing additional argument might be not a problem at all.
@premanandrao, @srividya-sundaram, @erichkeane, what do you think?
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.
tagging @kbobrovs to give his feedback as well since this was originally brought up by him.
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.
One more thing: this diagnostics warns that current implementation is not optimal.
I assume if compiler detects odr-use of constexpr
it can allocate a global constant/variable in device code and kernel function object can capture global object and avoid passing it via kernel argument. This seems to be valid implementation. Right?
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.
It's probably more useful to implement such diagnostics in performance profiler because passing additional argument might be not a problem at all.
I suspect many people (like myself) writing code similar to
constexpr int V = 137;
auto f = [=](Id i) -> int {
return (i * V).x;
};
will expect V to be compile-time constant inside the lambda. In some cases this expectation is not true and V is captured and hence is not a compile-time constant. This can potentially lead to performance problems.
I'm not sure what 'performance compiler' is. If it can be built from this github repo - I'm OK with making this feature available only in 'performance compiler'.
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.
FWIW, that is a fairly well known property of constexpr: It isn't necessarily a compile time constant unless you make it so in some way. I'm generally not in favor of a warning that tells you that the language is still working the way it is designed, particularly since there isn't a code-way to suppress this warning.
If we had some sort of perf-analysis tool, that would be a good place for that. Have we considered seeing if the Static Analysis effort would be a better place for this?
h.single_task<LambdaKernel>( | ||
[=]() { | ||
// constexpr 'OdrUsedVar' is odr-used here. | ||
const unsigned *ptr = &OdrUsedVar; // expected-warning {{captured constexpr 'OdrUsedVar' will be a kernel argument in device code}} |
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.
It's probably more useful to implement such diagnostics in performance profiler because passing additional argument might be not a problem at all.
I suspect many people (like myself) writing code similar to
constexpr int V = 137;
auto f = [=](Id i) -> int {
return (i * V).x;
};
will expect V to be compile-time constant inside the lambda. In some cases this expectation is not true and V is captured and hence is not a compile-time constant. This can potentially lead to performance problems.
I'm not sure what 'performance compiler' is. If it can be built from this github repo - I'm OK with making this feature available only in 'performance compiler'.
@@ -7449,6 +7449,9 @@ let CategoryName = "Lambda Issue" in { | |||
"%select{| explicitly}1 captured here">; | |||
def err_implicit_this_capture : Error< | |||
"implicit capture of 'this' is not allowed for kernel functions">; | |||
def warn_constexpr_kernel_arg : Warning< | |||
"captured constexpr '%0' will be a kernel argument in device code">, |
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.
"captured constexpr '%0' will be a kernel argument in device code">, | |
"captured constexpr '%0' will *not* be a compile-time constant in the device code">, |
I'm not in favor of putting a warning like this into the compiler. Warnings are supposed to be actionable, not informative. If there isn't a code-based way to suppress a warning (and get the behavior you want), they generally aren't put into the compiler. The issue here is closer to a bug (though not quite?) in the library. We're implementing conversion operators that aren't constexpr, so they cause us to need to use the variable in an ODR way, and thus need to be captured. This is a 'feature' of the language. IMO, if we want to warn on this, I'd suggest this go into the static analyzer. |
Agree. Possible action is to replace with
I see. But I wonder what share of SYCL developers know C++ well enough to have the right expectation of the result of the code here :) I think such warning would save many people some time and annoy just few experts. But I'll let you FE folks decide what's best here. |
Closing this PR since the above discussion suggests that this change should not be implemented in CFE. |
OpAtomicCompareExchangeWeak has been removed and #2665 added a validation for it. This pull request replaces OpAtomicCompareExchangeWeak with OpAtomicCompareExchange. Original commit: KhronosGroup/SPIRV-LLVM-Translator@eb64e4d795006d5
In some cases Clang FE captures
constexprs
variables into a lambda. This can cause performance problems in case of SYCL, becauseconstexprs
constexpr
will not appear as acompile-time
constant to the compilerThis patch warns users that a
constexpr
has been captured as a kernel argument and is not acompile-time
constant.The exact wordings of the warning message is open for wordsmithing.