-
Notifications
You must be signed in to change notification settings - Fork 699
Support Backend Specific Verifiers #3469
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
Conversation
b1f72f3
to
daa3eb3
Compare
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.
Looks pretty good to me! Just a couple minor nits, and agree would be nice to reduce the boilerplate stuff.
@shajrawi Overall, looks pretty good! Thanks for adding this feature! |
Somewhat tangential, but right now isSupported is used for two things.
To me it seems that it should be two different functions to answer those two questions. |
@shajrawi Can you also update |
@ayermolo The check for if a node is supported as quantized is a subset of |
Well isOpSupported can always call canQuantize (or whatever the other function name ends up). This way BE can control which nodes get quantized type, and also do additional checks on generic nodes to make sure they conform to BE requirements. Although I guess with ability to override verify the BE will be able to do it anyway after the check for isOpSupported. |
daa3eb3
to
2915513
Compare
@jfix71 I resolved the minor nits and updated |
311bcb4
to
36f193b
Compare
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.
Thanks for introducing those helpers! Looks better now.
include/glow/Backend/BackendUtils.h
Outdated
@@ -173,6 +173,46 @@ bool isOutput(const Placeholder *PH, const IRFunction &F); | |||
/// by the current function. | |||
bool isInput(const Placeholder *PH, const IRFunction &F); | |||
|
|||
/// Checks if typename C contains getFusedActivation() method |
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.
May be add "Use template meta-programming to check if ..."
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.
Using this approach is very clever! May be too clever ;-)
@@ -3017,5 +2997,11 @@ llvm::Error glow::optimizeFunction(Function *F, const Backend &B, | |||
::glow::optimize(F, cctx, B); | |||
} | |||
|
|||
return checkAllNodesSupported(*F, B); | |||
if (!B.verify(*F)) { |
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.
This deserves some comment IMHO. If I understand correctly, our strategy here is that we start using backend specific verification only after transformPostLowering
, i.e. only after some backend-specific nodes were introduced eventually. Is it a correct understanding? Please explain it in the comment then.
But I've got another related question here:
- We may call some graph optimizations multiple times. And we may call verify after each pass IIRC (see the pass manager details). Which verifier is currently called after each pass though and which one should be called? The backend-independent one or the backend-specific one? Or should it depend on the stage of compilation (e.g. call the backend-independent one before
transformPostLowering
and the backend-specific one aftertransformPostLowering
)? WDYT?
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.
Excellent observation! I changed this behavior and made it explicit in a separate commit that I added to this PR!
We should always do backend independent verifications of course, because we don't duplicate work, however, we should also do backend specific verifications form the moment we have the function in a lowered state.
The pass manager now checks the function state and adds extra verifications appropriately.
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 I can follow the logic of this new commit. Some of the optimizations are essentially backend-independent. But it seems like you demand now to always pass a Backend to the pass manager, even if the pass manager does not use it at the given stage of compilation. As a result you had to touch a bunch of places and pass a fake
Backend as a parameter now. This seems odd to me. And if this backend is always used (may be I overlooked something), which concrete Backend would you use before introducing target-specific nodes? Looks like you'd need a default Glow backend, which just captures the default Glow requirements in this case.
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 updated the the follow-up commit to avoid that. we now pass a pointer instead of a reference, with a default value of nullptr
, so we no longer need to pollute the code base with the fake
backend. I think we only need to pass the backend when we are doing backend specific optimizations. WDYT?
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.
Yess, makes sense.
8883258
to
596b7a2
Compare
@@ -3017,5 +2997,11 @@ llvm::Error glow::optimizeFunction(Function *F, const Backend &B, | |||
::glow::optimize(F, cctx, B); | |||
} | |||
|
|||
return checkAllNodesSupported(*F, B); | |||
if (!B.verify(*F)) { |
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 I can follow the logic of this new commit. Some of the optimizations are essentially backend-independent. But it seems like you demand now to always pass a Backend to the pass manager, even if the pass manager does not use it at the given stage of compilation. As a result you had to touch a bunch of places and pass a fake
Backend as a parameter now. This seems odd to me. And if this backend is always used (may be I overlooked something), which concrete Backend would you use before introducing target-specific nodes? Looks like you'd need a default Glow backend, which just captures the default Glow requirements in this case.
596b7a2
to
c4aac21
Compare
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.
Looks pretty good to me, just a series of nits.
c4aac21
to
07007e1
Compare
Amended the PR to address the nits :) |
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.
Looks pretty-good now!
I'm still thinking about the condition Backend verifications is always a super-set of F->verify()
. Is it really the case under all circumstances?
@@ -3017,5 +2997,11 @@ llvm::Error glow::optimizeFunction(Function *F, const Backend &B, | |||
::glow::optimize(F, cctx, B); | |||
} | |||
|
|||
return checkAllNodesSupported(*F, B); | |||
if (!B.verify(*F)) { |
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.
Yess, makes sense.
lib/Backend/Backend.cpp
Outdated
return checkAllNodesSupported(F); | ||
} | ||
|
||
bool Backend::verify(const IRFunction &IR) const { return true; } |
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.
Maybe it's better to make this pure virtual to force BE to deal with it, versus thinking it does something when it doesn't?
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 agree. Would like to turn them into pure virtual, but, I don't want to break any backends when doing this commit + I will intend to create a beginner / good first issue for someone to do write a verifier for the Habana backend.
07007e1
to
8b811ec
Compare
@opti-mix Fixed the nits + I made an explicit call to the target independent verifier to make sure. |
927b9ad
to
634115a
Compare
634115a
to
3d9c0c9
Compare
Fixed the nits / updated the comments. and all the tests pass. |
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.
Looks good! Great job!
Just address the final minor grammar nits (ideally, without introducing new ones ;-) and ship it!
🚀
3d9c0c9
to
833cd5c
Compare
833cd5c
to
2803a83
Compare
👏 🎆 |
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.
@shajrawi has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
2803a83
to
b2cd334
Compare
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.
@shajrawi has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.
Summary:
Adds support for backend-specific verifiers to Glow.
I removed the asserts in the backend specific code when executing Nodes with components that depend on the backend for validity and added verifiers to take their place.
There are two backend-specific verifiers: one that works on
Function
and one that takes inIRFunction
- this allows verification at different stages of the Glow pipeline.I also added two error types: one that indicates a verification error at initial IR generation (
COMPILE_UNSUPPORTED_IR_AFTER_GENERATE
) and one that indicates the faulty code appeared after IR optimizations (COMPILE_UNSUPPORTED_IR_AFTER_OPTIMIZE
).I also refactored the code, such that Graph Optimizer does not check that all nodes are supported directly, that should not be its job, it calls the verifier instead. The base method for the
Function
verifier does said check.Fixes #3450
Test Plan:
ninja test