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] Decompose kernel parameters and add inheritance support #1877

Merged
merged 60 commits into from
Jul 6, 2020

Conversation

elizabethandrews
Copy link
Contributor

@elizabethandrews elizabethandrews commented Jun 12, 2020

This PR redesigns 'parameter passing' support for kernel parameters of struct type. All struct type SYCL kernel arguments (except special SYCL types) are now decomposed and their individual fields are passed as separate OpenCL kernel arguments.

Following issues are fixed after this PR:

  1. Inheritance support for SYCL Kernel
  2. Accessors in base class
  3. Performance issues due to passing SYCL special types twice.
  4. Nested Arrays

This PR was a collaborative effort, with patches from Mariya Podchishchaeva and Elizabeth Andrews. For early testing, PR was updated periodically with changes from PR#1841 (Array support by Rajiv Deodhar). Changes from PR#1841 is not present in final diff since array support is now in intel:sycl.

rdeodhar and others added 11 commits June 8, 2020 17:04
Signed-off-by: rdeodhar <rajiv.deodhar@intel.com>
Signed-off-by: Mariya Podchishchaeva <mariya.podchishchaeva@intel.com>
Signed-off-by: Mariya Podchishchaeva <mariya.podchishchaeva@intel.com>
Vector types started appearing as top level arguments since they are
wrapped with cl::sycl::vec class.

Signed-off-by: Mariya Podchishchaeva <mariya.podchishchaeva@intel.com>
…They are decomposed and individual fields are passed

Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
through it's fields and initialize accessors using respective handlers.
Other fields of stream class are not handled.
@elizabethandrews
Copy link
Contributor Author

I think all lit tests except for those containing arrays should now pass. I think there are 3 with arrays in them.

@elizabethandrews
Copy link
Contributor Author

There is an issue with multiple streams in one command group. Debugging that now.

@iburyl
Copy link
Contributor

iburyl commented Jun 15, 2020

When I need to allow inherited accessors in my own branch, I need to change those two functions (clang/lib/Sema/SemaSYCL.cpp):

  • getAccessTarget - this one expected target template argument to be exactly the fourth one
  • isSyclAccessorType - this one expected the class of accessor to be named "accessor"

Are you sure, you do need changing those?

@Fznamznon
Copy link
Contributor

When I need to allow inherited accessors in my own branch, I need to change those two functions (clang/lib/Sema/SemaSYCL.cpp):

  • getAccessTarget - this one expected target template argument to be exactly the fourth one
  • isSyclAccessorType - this one expected the class of accessor to be named "accessor"

This approach won't work for user-defined classes which have accessor as base class. We need to handle this generic case as well.

Are you sure, you do need changing those?

We don't changing those.
If you mean that we do need change those, I'm not sure about it because of the reasons I explained above.

@Fznamznon
Copy link
Contributor

We don't changing those.
If you mean that we do need change those, I'm not sure about it because of the reasons I explained above.

I think to be sure here, we need to understand what is the purpose of your case. If your inherited accessor has its own implementation of __init method and you want it to be a top level kernel argument like regular accessor now, you may need to change those functions.

Comment on lines 798 to 810
// FIXME: Can this be refactored/handled some other way?
template <typename ParentTy, typename... Handlers>
static void VisitStreamRecord(CXXRecordDecl *Owner, ParentTy &Parent,
CXXRecordDecl *Wrapper, Handlers &... handlers) {
(void)std::initializer_list<int>{(handlers.enterStruct(Owner, Parent), 0)...};
VisitAccessorWrapperHelper(Wrapper, Wrapper->bases(), handlers...);
VisitAccessorWrapperHelper(Wrapper, Wrapper->fields(), handlers...);
for (const auto &Field : Wrapper->fields()) {
QualType FieldTy = Field->getType();
// Required to initialize accessors inside streams.
if (Util::isSyclAccessorType(FieldTy))
KF_FOR_EACH(handleSyclAccessorType, Field, FieldTy);
}
(void)std::initializer_list<int>{(handlers.leaveStruct(Owner, Parent), 0)...};
}
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 the best way for us is to re-implement stream class in SYCL headers, so it will look like accessor and we don't need to visit it's field in the compiler.
@againull , do you think it is possible?

clang/lib/Sema/SemaSYCL.cpp Outdated Show resolved Hide resolved
@iburyl
Copy link
Contributor

iburyl commented Jun 15, 2020

We don't changing those.
If you mean that we do need change those, I'm not sure about it because of the reasons I explained above.

I think to be sure here, we need to understand what is the purpose of your case. If your inherited accessor has its own implementation of __init method and you want it to be a top level kernel argument like regular accessor now, you may need to change those functions.

Our use case is having some_accessor, which is inherited from accessor.
We have no problem writing own __init (though avoiding that would be ideal).
Now this some_accessor is passed to kernel.

Will this use case be covered by your patch?

My own approach was: writing __init, changing getAccessTarget, for it to parse type parents, until it finds accessor, then check target template argument there + isSyclAccessorType is changed, to make some_accessor known to it. That worked.

@Pennycook

@Fznamznon
Copy link
Contributor

Our use case is having some_accessor, which is inherited from accessor.
We have no problem writing own __init (though avoiding that would be ideal).
Now this some_accessor is passed to kernel.

Our intention was to implement support for user-defined inherited accessors. So passing some class which have accessor in base should work and __init writing is not required.

rdeodhar and others added 4 commits June 15, 2020 09:00
Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
@elizabethandrews elizabethandrews changed the title [WIP][SYCL][Do not review]Decompose kernel parameters and inheritance support Decompose kernel parameters and add inheritance support Jul 2, 2020
@elizabethandrews elizabethandrews marked this pull request as ready for review July 2, 2020 18:03
@elizabethandrews elizabethandrews changed the title Decompose kernel parameters and add inheritance support [SYCL] Decompose kernel parameters and add inheritance support Jul 2, 2020
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.

NO comments on this for me, the stuff I understand all looks right.

erichkeane
erichkeane previously approved these changes Jul 2, 2020
rdeodhar
rdeodhar previously approved these changes Jul 2, 2020
Copy link
Contributor

@rdeodhar rdeodhar left a comment

Choose a reason for hiding this comment

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

All the changes look good to me.

premanandrao
premanandrao previously approved these changes Jul 2, 2020
…upport_2

Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
@elizabethandrews
Copy link
Contributor Author

Merged latest changes from intel:sycl, fixing conflict (Just a variable name change).

@Fznamznon
Copy link
Contributor

@intel/llvm-reviewers-runtime there are some runtime tests, could someone review them, please?

Copy link
Contributor

@s-kanaev s-kanaev left a comment

Choose a reason for hiding this comment

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

The runtime tests look good to me, except for a single comment there.
Also, I believe it's an extension and not by-specification. Hence, a link to the extension proposal/spec would be a nice to have.

@Fznamznon
Copy link
Contributor

Fznamznon commented Jul 3, 2020

Also, I believe it's an extension and not by-specification. Hence, a link to the extension proposal/spec would be a nice to have.

This is not an extension. SYCL specification technically doesn't prohibit inheritance for kernel arguments, kernel function objects and accessors, so this patch only adds handling of these missed cases.

@s-kanaev
Copy link
Contributor

s-kanaev commented Jul 3, 2020

This is not an extension. SYCL specification technically doesn't prohibit inheritance for kernel arguments, kernel function objects and accessors, so this patch only adds handling of these missed cases.

OK, then.

Copy link
Contributor

@bader bader left a comment

Choose a reason for hiding this comment

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

A couple of improvement suggestions, which can be applied in separate PRs.

Comment on lines +7 to +12
// CHECK-NEXT: { kernel_param_kind_t::kind_std_layout, 4, 12 },
// CHECK-NEXT: { kernel_param_kind_t::kind_std_layout, 4, 16 },
// CHECK-NEXT: { kernel_param_kind_t::kind_std_layout, 4, 20 },
// CHECK-NEXT: { kernel_param_kind_t::kind_std_layout, 4, 24 },
// CHECK-NEXT: { kernel_param_kind_t::kind_std_layout, 4, 28 },
// CHECK-NEXT: { kernel_param_kind_t::kind_std_layout, 4, 32 },
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to decompose a struct consisting of standard trivially-copiable C++ types (i.e. which doesn't encapsulate a non-USM pointer or non-standard C++ type e.g. image or sampler).
Sending it like this will impact performance:

  • we set 6 parameters instead of one, which means runtime overhead on calling "setArg" 6 times + potentially use more registers than needed to pass six 4-byte values instead of one 24-byte value
  • it might complicate JIT compiler analysis (or may not).

I'm okay if we address this in follow-up commit.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, we were planning to add this optimization after implementing basic functionality. I've created an issue to keep track on that #2043. @elizabethandrews , would you mind taking this one?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure will do.

Comment on lines +2684 to +2688
Util::DeclContextDesc{clang::Decl::Kind::Namespace, "cl"},
Util::DeclContextDesc{clang::Decl::Kind::Namespace, "sycl"},
Util::DeclContextDesc{clang::Decl::Kind::Namespace, "detail"},
Util::DeclContextDesc{clang::Decl::Kind::Namespace, "half_impl"},
Util::DeclContextDesc{Decl::Kind::CXXRecord, Name}};
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, add an attribute to annotate SYCL types like accessor, sampler, image. It's much more reliable approach than declaration name, which introduces hard-coded dependency on exact symbol name in the runtime library.
I suppose we need only one attribute to detect special types which must be handled as separate kernel parameters. If not, we can parameterize the attribute.

This refactoring can be done in a separate PR.
Tagging @Naghasan, who was going to contribute similar attribute from ComputeCPP implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Please, add an attribute to annotate SYCL types like accessor, sampler, image. It's much more reliable approach than declaration name, which introduces hard-coded dependency on exact symbol name in the runtime library.
I suppose we need only one attribute to detect special types which must be handled as separate kernel parameters. If not, we can parameterize the attribute.

This refactoring can be done in a separate PR.
Tagging @Naghasan, who was going to contribute similar attribute from ComputeCPP implementation.

Right now just one attribute is not enough since we have differences between handling of different classes, especially in integration header support. It seems runtime library needs to handle each type in a different way, I have no idea how to redo it so it will be unified across different SYCL types.
Right now we can start with parameterized attribute, i.e. for example:

class accessor {
...
__attribute__((sycl_special_type(accessor))) DataT *Data;
} 

...
class sampler {
...
__attribute__((sycl_special_type(sampler))) ocl_sampler_t Sampler;
} 

Also, we can discuss it in upcoming upstreaming meeting.
I've created an issue to keep track on that #2041.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd like to point out that clang is able to differentiate sampler from accessor w/o any attributes - they are different types (pointer type vs __ocl_sampler_t).

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, makes sense.

@bader bader merged commit 0b2de9e into intel:sycl Jul 6, 2020
FreddyLeaf pushed a commit to FreddyLeaf/llvm that referenced this pull request Mar 22, 2023
This type instruction describes a string, mostly for Fortran 90.

Spec:
KhronosGroup/SPIRV-Registry#186

Original commit:
KhronosGroup/SPIRV-LLVM-Translator@beecd9d
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants