Skip to content
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

Merged
merged 9 commits into from
Jul 22, 2020
Merged

[SYCL] Error for implicit capture of this pointer inside a sycl kernel #2029

merged 9 commits into from
Jul 22, 2020

Conversation

asudarsa
Copy link
Contributor

@asudarsa asudarsa commented Jul 2, 2020

Change-Id: Icf4145a3cf3732a0ff28f0ada9880a24b97b5a0d
Signed-off-by: Arvind Sudarsanam [email protected]

Change-Id: Icf4145a3cf3732a0ff28f0ada9880a24b97b5a0d
Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
Comment on lines 1655 to 1664
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);
}
}
}
Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

Comment on lines 7309 to 7311
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">;
Copy link
Contributor

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 =.

Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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?

Copy link
Contributor

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.

Copy link
Contributor

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}}
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@asudarsa
Copy link
Contributor Author

asudarsa commented Jul 9, 2020

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.
I am currently running into some local testing issue which I have reported and will submit a new patch once I can test it. Thanks

@asudarsa asudarsa requested a review from a team as a code owner July 14, 2020 16:18
@asudarsa asudarsa requested a review from rbegam July 14, 2020 16:18
asudarsa added 2 commits July 14, 2020 09:23
Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
@asudarsa asudarsa requested review from bader and againull July 14, 2020 18:26
@@ -0,0 +1,28 @@
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -verify %s
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 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>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#include <sycl.hpp>

Is this include really needed?

asudarsa added 2 commits July 20, 2020 07:08
Signed-off-by: Arvind Sudarsanam <[email protected]>
Signed-off-by: Arvind Sudarsanam <[email protected]>
againull
againull previously approved these changes Jul 20, 2020
sycl/include/CL/sycl/handler.hpp Show resolved Hide resolved
Copy link
Contributor

@elizabethandrews elizabethandrews left a 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?

clang/include/clang/Basic/DiagnosticSemaKinds.td Outdated Show resolved Hide resolved
Signed-off-by: Arvind Sudarsanam <[email protected]>
Copy link
Contributor

@erichkeane erichkeane left a 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.

clang/lib/Sema/SemaSYCL.cpp Show resolved Hide resolved
Signed-off-by: Arvind Sudarsanam <[email protected]>
@erichkeane
Copy link
Contributor

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.

Copy link
Contributor

@rbegam rbegam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants