-
Notifications
You must be signed in to change notification settings - Fork 744
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] Error for implicit capture of this pointer inside a sycl kernel #2029
Conversation
Change-Id: Icf4145a3cf3732a0ff28f0ada9880a24b97b5a0d Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
clang/lib/Sema/SemaSYCL.cpp
Outdated
if (KernelLambda->isLambda()) { | ||
llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; | ||
FieldDecl *ThisCapture; | ||
KernelLambda->getCaptureFields(Captures, ThisCapture); | ||
for (const LambdaCapture &LC : KernelLambda->captures()) { | ||
if (LC.capturesThis() && LC.isImplicit()) { | ||
Diag(LC.getLocation(), diag::err_implicit_this_capture); | ||
} | ||
} | ||
} |
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.
Eeh, this is a bit outside of the whole Visitor model that we have in SemaSYCL. We often use SyclKernelFieldChecker
to check kernel fields. The problem that it actually checks fields not captures. Right now, I don't know how to integrate it into the current visitor model, though.
@elizabethandrews , @erichkeane , any ideas?
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.
Yeah, theres not really a good way to do this with the field checker. If this is a limitation in the standard, it is definitely something that should be diagnosed.
However, this message is wrong I think, this also looks like it will diagnose on capture with '&' of this as well.
Also, 1656,57, and 58 are unnecessary as far as I can tell, those lines likely need to be removed.
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.
Actually SYCL 1.2.1 standard prohibits all sorts of passing pointers from host to device, however we support USM extension that actually allows some pointers to be passed to the kernel, but this
pointer is definitely not the case of USM pointer and accidental capture of this
pointer is very common in user's code and always produces fails in run time. This definitely should be diagnosed.
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.
Actually SYCL 1.2.1 standard prohibits all sorts of passing pointers from host to device, however we support USM extension that actually allows some pointers to be passed to the kernel, but
this
pointer is definitely not the case of USM pointer and accidental capture ofthis
pointer is very common in user's code and always produces fails in run time. This definitely should be diagnosed.
I think this should be an error only if strict compliance to SYCL 1.2.1 is requested; if USM is enabled, it should be a warning instead.
My understanding is that if a class is allocated in USM, the this
pointer is a USM pointer and can be safely used in kernels.
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.
Hi @Pennycook , Thanks for the comment. I agree that we should deal with USM pointers as a special case. Is there a way that the compiler can know if USM is enabled? Also, for a given class object, is it possible for the compiler to check if it is allocated in USM? I tried looking around in compiler sources and I did not see any other instance where we are checking for USM. May be I missed something.
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.
@erichkeane. Thanks for your comment. I will remove 1656-58. I was using them earlier. Also, I will check to see if using [&] results in similar runtime error and update the error message accordingly.
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.
Is there a way that the compiler can know if USM is enabled?
Adding @jbrodman and @AlexeySachkov. I seem to remember talk of providing something like an -fsycl-usm
flag to control the USM extension, but I don't know what it's implementation status is.
Also, for a given class object, is it possible for the compiler to check if it is allocated in USM?
Unfortunately not. Whether the object was allocated in USM or not is something that can only be determined at runtime. This is why I suggested that we generate a warning in this case; a user would then see at compile-time that what they're doing may be unsafe, but would be free to ignore the warning if they wanted.
Alternatively, if we decide to stick with an error for implicit capture of this
in all situations, we could display different error messages. If USM is disabled, capture of this
is not allowed for SYCL kernels. If USM is enabled, capture of this
is only allowed if the class was allocated in USM, and the user should explicitly specify this
in the capture list if it was intended.
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.
Hi @Pennycook
Thanks so much for the detailed feedback. I agree that we can emit two different error messages. But, I think that can be captured as a separate task. Please advise.
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 think 'strict-sycl' (or sycl-strict?) was intended for this type of extension. I think we intended to have pointers in general handled with that flag.
In 'strict' SYCL mode, ALL captures of pointers (including 'this') is supposed to be ill-formed, by my understanding, so the extra rule of 'implicit capture of this' seems unnecessary*. That said, having our USM extension require explicit capture seems like a good idea, accidental capture of 'this' is unfortunately quite easy.
*The exception of course is capture via '=', where someone who doesn't understand how implicit this capture works would be burned. Since '=' means "take the state as it is now", accidental capture of 'this' is particularly surprising/dangerous.
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.
Yes, accidental capture of this through [=] has caused a lot of pain.
def err_implicit_this_capture : Error< | ||
"implicit capture of 'this' with a capture default of '=' is not allowed " | ||
"for kernel functions in SYCL 1.2.1">; |
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'm not sure that we need to mention =
in this diagnostic at all, because AFAIK SYCL kernel lambdas can be defined only with =
.
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.
Do we prohibit & capture? I realize that we can't capture references (right?!), but & capture of 'this' as a slightly different meaning.
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.
We diagnose captured references (I mean the fields of kernel object that have reference type), but I don't remember diagnostic for the whole &
lambda capture. Isn't it covered by captured references diagnostic? Should we diagnose it separately?
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.
THAT covers it for the most part (thought it might be confusing since adding a line to a lambda will cause it to actually capture by reference), but capturing 'this' is a confusing story. Capturing 'this' by reference is exactly the same as not capturing by this, since the pointer cannot change.
We likely want to change the error message to say 'implicit capture of this', which is what the rest of the patch implements.
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.
Is there a reason only implicit capture of this
is not allowed? I would assume whatever issues arise from capturing this
would exist for implicit and explicit capture?
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 question. I somehow was under impression that kernel lambdas can use only implicit capture, however I've opened the spec where it describes how to write kernel lambda and it says (pt. 4.8.9.2):
The kernel lambda must use copy for all of its captures (i.e. [=]).
For me this statement doesn't prohibit copy for explicit captures.
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.
Yes, there is no reason to forbid explicit captures.
kernel<class kernel_wrapper>( | ||
[=]() { | ||
int acc[1] = {5}; | ||
acc[0] *= member; // expected-error{{implicit capture of 'this' with a capture default of '=' is not allowed for kernel functions in SYCL 1.2.1}} |
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 spent some time to actually understand how this
was actually captured. Can we also add a clarifying note?
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.
Hi @Fznamznon , Thanks for the comment. Can you please let me know what we can mention in the clarifying note? Thanks.
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 wanted some note like
'this' is captured through usage of
member field inside the lambda
Although, I don't see a good way to implement it now, so, you can skip this comment.
I am looking at the failures now. In one of the existing test cases, a member function of a class is called inside the kernel and the compiler reports 'my' error message. I think this is correct behavior. I can update the test to have explicit capture of 'this' pointer and check if it passes after that. |
Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
@@ -0,0 +1,28 @@ | |||
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -verify %s |
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.
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -verify %s | |
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -fsyntax-only -verify %s |
@@ -0,0 +1,28 @@ | |||
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -verify %s | |||
|
|||
#include <sycl.hpp> |
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.
#include <sycl.hpp> |
Is this include really needed?
Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
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.
LGTM except for diagnostic wording. @erichkeane can you also take a look?
Signed-off-by: Arvind Sudarsanam <[email protected]>
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.
1 coding-standard nit. Otherwise LGTM.
Signed-off-by: Arvind Sudarsanam <[email protected]>
As a note for the future, we likely want to extract tests like this (that check the lambda itself) into a separate function. I believe @cperkinsintel has another patch that is a good candidate for this sort of thing, so when he goes to do that he likely wants to extract ALL lambda checking into its own function. |
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.
LGTM
Change-Id: Icf4145a3cf3732a0ff28f0ada9880a24b97b5a0d
Signed-off-by: Arvind Sudarsanam [email protected]