Skip to content

Change PI_CALL syntax from PI_CALL(pi, ...Args) to PI_CALL(pi)(...Args); #843

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 12 commits into from
Nov 25, 2019

Conversation

garimagu
Copy link
Contributor

@garimagu garimagu commented Nov 19, 2019

Changes done:

  1. Keeping PI API function pointers in a structure. Passing this structure to the plugin. The plugin populates the function pointers appropriately. This makes us have a single call to the plugin to bind all APIs. 2 commits.
  2. Commit 3 changes the PI_CALL syntax. The call looks like a constructor call and then a functor call on the constructor.
  3. Commit 4,5 does other formatting changes and introduces the PI_CALL_THROW Macro.

@garimagu
Copy link
Contributor Author

review only the last commit.

@garimagu
Copy link
Contributor Author

Some cleaning of comments is needed.

@romanovvlad
Copy link
Contributor

It would be nice if you put rationale for such changes in the commit message.

@@ -86,13 +86,13 @@ template <typename AllocatorT> class SYCLMemObjT : public SYCLMemObjI {

RT::PiMem Mem = pi::cast<RT::PiMem>(MInteropMemObject);
RT::PiContext Context = nullptr;
PI_CALL(RT::piMemGetInfo, Mem, CL_MEM_CONTEXT, sizeof(Context), &Context,
nullptr);
RT::piCheckResult(PI_CALL_NOCHECK(piMemGetInfo)(
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks...kind of strange: what so specific is being done by piCheckResult that cannot be done by regular PI_CALL?

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 even need piCheckResult. We should write error specific result checking for each pi invocation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a mistake. I think it may have happened because of the changes being done in stages.In some intermediate stage I have chosen PI_CALL_RESULT for some reason and then changed it to this directly.

Copy link
Contributor Author

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 even need piCheckResult. We should write error specific result checking for each pi invocation.

Are you saying at each PI_CALL site, we should check the error return code and perform an action appropriately?
The usage of piCheckResult() API or in PI_CALL, means that the site of call only wants to check if a PI_SUCCESS is received and it throws a runtime_error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@romanovvlad Please confirm if i understood you correct/addressed your concern.

Comment on lines 144 to 159
if (PI_TRACE_ENABLED) {
std::cout << "---> " << m_FnName << "(";
printArgs(args...);
}

auto r = m_FnPtr(args...);
PiResult r = m_FnPtr(args...);

if (m_TraceEnabled) {
if (PI_TRACE_ENABLED) {
std::cout << ") ---> ";
std::cout << (print(r), "") << std::endl;
}
return r;
Copy link
Contributor

Choose a reason for hiding this comment

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

So, +2 getenv calls on each PI API call, right? I guess this is some kind of overkill and definitely will affect performance

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed the code.

#define _PI_API(api) \
template <> \
Trace<decltype(&::api), \
(offsetof(_pi_plugin::FunctionPointers, api))>::Trace();
Copy link
Contributor

@bjoernknafla bjoernknafla Nov 20, 2019

Choose a reason for hiding this comment

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

Is the implementation missing here (might be further below)?

Is this specialization required? Might it work to declare the constructor inside the Trace class as Trace() = default; (and declaring the function pointer inside the class as follows FnType m_FnPtr = nullptr; ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The implementation is in pi.cpp
I'm sorry I didn't understand your suggestion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@bjoernknafla Can you explain your suggestion again?

Copy link
Contributor Author

@garimagu garimagu left a comment

Choose a reason for hiding this comment

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

added suggested changes to commit#5

@@ -86,13 +86,13 @@ template <typename AllocatorT> class SYCLMemObjT : public SYCLMemObjI {

RT::PiMem Mem = pi::cast<RT::PiMem>(MInteropMemObject);
RT::PiContext Context = nullptr;
PI_CALL(RT::piMemGetInfo, Mem, CL_MEM_CONTEXT, sizeof(Context), &Context,
nullptr);
RT::piCheckResult(PI_CALL_NOCHECK(piMemGetInfo)(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a mistake. I think it may have happened because of the changes being done in stages.In some intermediate stage I have chosen PI_CALL_RESULT for some reason and then changed it to this directly.

@@ -86,13 +86,13 @@ template <typename AllocatorT> class SYCLMemObjT : public SYCLMemObjI {

RT::PiMem Mem = pi::cast<RT::PiMem>(MInteropMemObject);
RT::PiContext Context = nullptr;
PI_CALL(RT::piMemGetInfo, Mem, CL_MEM_CONTEXT, sizeof(Context), &Context,
nullptr);
RT::piCheckResult(PI_CALL_NOCHECK(piMemGetInfo)(
Copy link
Contributor Author

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 even need piCheckResult. We should write error specific result checking for each pi invocation.

Are you saying at each PI_CALL site, we should check the error return code and perform an action appropriately?
The usage of piCheckResult() API or in PI_CALL, means that the site of call only wants to check if a PI_SUCCESS is received and it throws a runtime_error.

Comment on lines 144 to 159
if (PI_TRACE_ENABLED) {
std::cout << "---> " << m_FnName << "(";
printArgs(args...);
}

auto r = m_FnPtr(args...);
PiResult r = m_FnPtr(args...);

if (m_TraceEnabled) {
if (PI_TRACE_ENABLED) {
std::cout << ") ---> ";
std::cout << (print(r), "") << std::endl;
}
return r;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed the code.

#define _PI_API(api) \
template <> \
Trace<decltype(&::api), \
(offsetof(_pi_plugin::FunctionPointers, api))>::Trace();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The implementation is in pi.cpp
I'm sorry I didn't understand your suggestion.

@garimagu
Copy link
Contributor Author

garimagu commented Nov 20, 2019

@smaslov-intel Please check the changes.
I am yet to make the clang-format updates.

@garimagu
Copy link
Contributor Author

@smaslov-intel Please check the clang-format changes.
@erichkeane @bader : Is it ok to add changes in the clang-format config file in llvm directory?

@erichkeane
Copy link
Contributor

Is it possible to just alter the clang-format at a much lower directory? It seems no one alters the 'root' version ever in community. BUT, I suspect you could add sometihng at the /sycl/include level.

@garimagu
Copy link
Contributor Author

Is it possible to just alter the clang-format at a much lower directory? It seems no one alters the 'root' version ever in community. BUT, I suspect you could add sometihng at the /sycl/include level.

Yes. I can do that. There is no .clang-format file in sycl folder.
Can i add it there? Or should I make two, one for each include and source directory?

@erichkeane
Copy link
Contributor

Is it possible to just alter the clang-format at a much lower directory? It seems no one alters the 'root' version ever in community. BUT, I suspect you could add sometihng at the /sycl/include level.

Yes. I can do that. There is no .clang-format file in sycl folder.
Can i add it there? Or should I make two, one for each include and source directory?

If it'll work, I think just the root 'sycl' directory would be fine.

@garimagu garimagu force-pushed the private/garimagu/pi_callsemanticchange branch from 1000107 to be01470 Compare November 21, 2019 19:19
Copy link
Contributor

@smaslov-intel smaslov-intel left a comment

Choose a reason for hiding this comment

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

Mostly looks good to me, just rather minor suggestions.

// TODO: Absorb this utility in Trace Class
template <typename Exception> inline void piCheckThrow(PiResult pi_result) {
template <typename Exception = cl::sycl::runtime_error>
inline void piCheckResult(PiResult pi_result) {
Copy link
Contributor

Choose a reason for hiding this comment

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

we decided to not prepend with "pi" utilities in "pi" namespace, so this would be just checkResult, or maybe better check PiResult

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

template <typename... Args> PiResult operator()(Args... args) {
if (m_TraceEnabled)
bool enableTrace = PI_TRACE_ENABLED;
Copy link
Contributor

Choose a reason for hiding this comment

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

It is still a getenv() per each PI call, which is redundant. Please make this a static member of the class and initialize just once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


template <typename FnType> class Trace {
template <typename FnType, size_t FnOffset> class Trace {
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 comments about what this class is doing, and I think it should be named "Call", and not "Trace" as this is its primary functionality. Also a good place to explain in comment what the template arguments are for.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to CallPi.

bool Trace<FnType>::m_TraceEnabled = (std::getenv("SYCL_PI_TRACE") != nullptr);
template <typename FnType, size_t FnOffset,
typename Exception = cl::sycl::runtime_error>
class TraceCheck : private Trace<FnType, FnOffset> {
Copy link
Contributor

Choose a reason for hiding this comment

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

TraceCheck -> CallAndCheck

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed to CallPiAndCheck

std::cout << ") ---> ";
std::cout << (print(r), "") << std::endl;
}
return r;
}
};

template <typename FnType>
bool Trace<FnType>::m_TraceEnabled = (std::getenv("SYCL_PI_TRACE") != nullptr);
template <typename FnType, size_t FnOffset,
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the header, please explain the interface here, i.e. what the exception argument stands for, and what the class is for

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. Please see if it looks good.

RT::initialize(); \
RT::piCheckResult(PI_TRACE(pi)(__VA_ARGS__)); \
}
#define PI_ASSERT(cond, msg) RT::assertion((cond), "assert: " msg);
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need this macro?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

in Pi::Cast. Moved it closer to the API.


#define PI_TRACE_ONLY(func) RT::Trace<decltype(func)>(func, #func)
namespace RT = cl::sycl::detail::pi;
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest to rename RT to PI (not in this change-set please)

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. One change-set just for formatting and Naming.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And one for the version and version handshaking.

const char SupportedVersion[] = "1.1";
#define STRING_HELPER(a) #a
#define STRINGIZE(a,b) STRING_HELPER(a.b)
const char SupportedVersion[] = STRINGIZE(_PI_H_VERSION_MAJOR,_PI_H_VERSION_MINOR);
Copy link
Contributor

Choose a reason for hiding this comment

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

since the arguments are defined in pi.h why not define the string there too? And then you don't need to repeat stringizing utilities here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wanted to define a PI_H_VERSION_STRING macro, which uses _PI_H_VERSION_MAJOR, _PI_H_VERSION_MINOR.
but then I didn't want to define the STRINGIZE macros in the .cpp file.
I have made some changes. Let me know what you think.

@garimagu garimagu force-pushed the private/garimagu/pi_callsemanticchange branch from be01470 to caa1506 Compare November 22, 2019 22:15
@garimagu
Copy link
Contributor Author

Rebase and conflict resolution.

@garimagu
Copy link
Contributor Author

@smaslov-intel Please check the changes done.

smaslov-intel
smaslov-intel previously approved these changes Nov 22, 2019
Copy link
Contributor

@smaslov-intel smaslov-intel left a comment

Choose a reason for hiding this comment

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

LGTM

// FnOffset- Offset to the Function Pointer in the piPlugin::FunctionPointers
// structure.Used to differentiate between APIs with same pointer type, Eg:
// piDeviceRelease and piDeviceRetain. Differentiation needed to avoid
// duplicate instantiation of class in pi.cpp.
Copy link
Contributor

Choose a reason for hiding this comment

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

please clarify that this is really a stability issue, i.e. you cannot do different template specializations for different PI interfaces (having same type) without this

template <> \
CallPi<decltype(&::api), \
(offsetof(pi_plugin::FunctionPointers, api))>::CallPi() { \
template <> CallPi<decltype(&::api)>::CallPi() { \
Copy link
Contributor

Choose a reason for hiding this comment

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

where had the offset parameter gone?

Copy link
Contributor Author

@garimagu garimagu Nov 24, 2019

Choose a reason for hiding this comment

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

Sorry about that. I changed the code to check the exact error message I get; changed it back. tested it, but during final cleaning of the code included the wrong PiCall Definition.

datastructure with all function pointers. Extension to this will allow
us to bind multiple plugins.

Signed-off-by: Garima Gupta <[email protected]>
PI_CALL( or PI_CALL_RESULT( and other required changes.

Signed-off-by: Garima Gupta <[email protected]>
to PI_CALL(pi)(...Args);
Required extension of Trace class.
Changed the syntax at all call sites.

Signed-off-by: Garima Gupta <[email protected]>
Changed the clang-format config file to consider
PI_CALL/PI_CALL_THROW/PI_CALL_NOCHECK as typenames instead of being
functions.

Signed-off-by: Garima Gupta <[email protected]>
introduced during rebase-conflict resolution.
Bug fix in unittests/pi/PlatformTest.cpp.

Signed-off-by: Garima Gupta <[email protected]>
Rectified merge conflict issues.

Signed-off-by: Garima Gupta <[email protected]>
@garimagu garimagu force-pushed the private/garimagu/pi_callsemanticchange branch from ac5617f to f8480a0 Compare November 24, 2019 00:18
@garimagu
Copy link
Contributor Author

rebased, resolved merge conflict issues.

smaslov-intel
smaslov-intel previously approved these changes Nov 24, 2019
Copy link
Contributor

@smaslov-intel smaslov-intel left a comment

Choose a reason for hiding this comment

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

Thanks! Looks good to me.

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.

LGTM. A few minor comments.

// Template Arguments:
// FnType - Type of Function pointer to the PI API.
// FnOffset- Offset to the Function Pointer in the piPlugin::FunctionPointers
// structure. Used to differentiate between APIs with same pointer type, Eg:
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
// structure. Used to differentiate between APIs with same pointer type, Eg:
// structure. Used to differentiate between APIs with same pointer type, E.g.:

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

// structure. Used to differentiate between APIs with same pointer type, Eg:
// piDeviceRelease and piDeviceRetain. Differentiation needed to avoid
// redefinition error during explicit specialization of class in pi.cpp.
// Members: Initialiaed in default constructor in Class Template Specialization.
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
// Members: Initialiaed in default constructor in Class Template Specialization.
// Members: Initialized in default constructor in Class Template Specialization.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

// Template Arguments:
// FnType, FnOffset - for CallPi Class.
// Exception - The type of exception to throw if PiResult of a call is not
// PI_SUCCESS. default is cl::sycl::runtime_error.
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
// PI_SUCCESS. default is cl::sycl::runtime_error.
// PI_SUCCESS. Default value is cl::sycl::runtime_error.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

// To check the result use checkPiResult.
// Usage:
// PiResult Err = PI_CALL_NOCHECK(pi)(args);
// RT::checkPiResult(Err); <- Checks Result and throws a runtime error
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
// RT::checkPiResult(Err); <- Checks Result and throws a runtime error
// RT::checkPiResult(Err); <- Checks Result and throws a runtime_error

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

// PI interface supports lower version of PI.
// TODO: Take appropriate actions.
return PI_INVALID_OPERATION;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

Copy link
Contributor Author

@garimagu garimagu Nov 25, 2019

Choose a reason for hiding this comment

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

I think Bjoern suggested this too. I forgot to do the change.

#define PI_CALL_NOCHECK(pi) \
RT::CallPi<decltype(&::pi), (offsetof(pi_plugin::FunctionPointers, pi))>()

// Use this macro to call the API, trace the call, check the return and throw a
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 "throw a Exception" should be either "throw an Exception" or "throw the Exception".

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

@garimagu
Copy link
Contributor Author

@bader Please approve and merge.

@bader bader merged commit e3b76be into intel:sycl Nov 25, 2019
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.

7 participants