Skip to content

[SYCL] Improve mock PI plugin #7129

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

Merged
merged 5 commits into from
Oct 25, 2022

Conversation

romanovvlad
Copy link
Contributor

@romanovvlad romanovvlad commented Oct 20, 2022

The patch adds more logic to default redefinitions of PI APIs:

  1. Allocate, refcount and deallocate various handles
  2. Handle sub-buffer creation

Also the patch adds support for adding PI functions to be called in addition (before or after) to the original function. This allows intercepting PI API calls for introspection while still allowing original function take care of handles. Or add some post processing of the returned values.

The patch adds more logic to default redefinitions of PI APIs:
1. Allocate, refcount and deallocated various handles
2. Handle sub-buffer creation

Also the patch adds support for adding PI functions to be called in
addition (before or after) to the original function. This allows
intersecting PI API calls for introspection while still allowing
original function take care of handles. Or add some post processing
of the returned values.
@aelovikov-intel
Copy link
Contributor

aelovikov-intel commented Oct 20, 2022

I love the idea of what we are doing here, but I'm not sure about how. However, please consider the below just as an alternative idea and not a request to make any changes.

What if do more functional programming style here? Pseudocode:

// Maybe an extra overload in addition to pre-existing simpler functionality.
Mock.redefine([&](std::function OldEntry) -> std::function {
  return [&]() {
    // Code before
    OldEntry();
    // Code after.
   };
});

or

Mock.redefine_wrap([&](auto OldEntry) {
   // Code before
  OldEntry
  // Code after
});

This is likely slower in run time but I think that for testing infrastructure the tradeoff between easier maintainability/speed could be more biased towards the former.

@romanovvlad
Copy link
Contributor Author

I love the idea of what we are doing here, but I'm not sure about how. However, please consider the below just as an alternative idea and not a request to make any changes.

What if do more functional programming style here? Pseudocode:

// Maybe an extra overload in addition to pre-existing simpler functionality.
Mock.redefine([&](std::function OldEntry) -> std::function {
  return [&]() {
    // Code before
    OldEntry();
    // Code after.
   };
});

or

Mock.redefine_wrap([&](auto OldEntry) {
   // Code before
  OldEntry
  // Code after
});

This is likely slower in run time but I think that for testing infrastructure the tradeoff between easier maintainability/speed could be more biased towards the former.

We could do something like that https://godbolt.org/z/T3oPbvKv8 .
Not sure why it's better though, current tests show that people tend to provide a function pointer rather than write a lambda. Also(not sure we will ever need this), but it's not clear how to undo such a wrapper.

Copy link
Contributor

@steffenlarsen steffenlarsen left a comment

Choose a reason for hiding this comment

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

This is super good! It will make it a lot easier to for example add specific info queries without having to redefine the entire info query function. Few comments.

@@ -130,6 +221,10 @@ class PiMock {
PiMock(const PiMock &) = delete;
PiMock &operator=(const PiMock &) = delete;
~PiMock() {
// Since the plugin relies on the global vars to store function pointers we
// need to reset them for the new PiMock plugin instance
// TODO: Make function pointers array for each PiMock instance?
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 we would need that in case gtest ever decides to run tests in parallel. It may be enough to make the arrays thread_local. That might have problems when a specific test is multi-threaded though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As an alternative we could:

  1. Create a global map pi_platfrom to array of function pointers map
  2. create a global map from every handle(void*) to pi_platform
  3. update the map(from 2)) any time we create or remove a handle in the mock functions
  4. in the proxy function, for a given handle find a corresponding pi_platform using the map from 2)
  5. Using pi_platform find an array of function pointers from 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 think that might be a good solution to the problem. We could even simplify the map (2) a little, defining a space for which a given platform can use, e.g. the first platform can create handles 0-10000, the next can use 10000-20000, etc. Biggest problem is if someone overwrites the behavior of a function returning handles and return something not in the allocated range/in the map.

Copy link
Contributor

@steffenlarsen steffenlarsen left a comment

Choose a reason for hiding this comment

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

Good stuff!

@pvchupin pvchupin merged commit 1f35a39 into intel:sycl Oct 25, 2022
@pvchupin
Copy link
Contributor

@pvchupin
Copy link
Contributor

@romanovvlad, please see post commit issue: https://github.com/intel/llvm/actions/runs/3322958425/jobs/5492696367

There are actually few separate issues in different configurations. Probably it would be the best to revert at this point and reapply as soon as addressed.

pvchupin pushed a commit that referenced this pull request Oct 25, 2022
pvchupin pushed a commit that referenced this pull request Oct 25, 2022
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.

5 participants