-
Notifications
You must be signed in to change notification settings - Fork 699
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
Allow Compilation without Collecting Constants #2246
Allow Compilation without Collecting Constants #2246
Conversation
There's new behaviour here (compiling without collecting) that I don't think we're testing anywhere. Can we write a test to cover this? |
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.
Sorry, but I'm having trouble seeing the desired end-state here. Can you explain in a bit more detail why we need to split out constant collection?
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.
Sorry I'm pretty repetitive on the "blank lines separating definitions" theme, but that is a major bugaboo for me ;-).
@@ -45,7 +45,11 @@ class CPUBackend : public BackendUsingGlowIR { | |||
std::unique_ptr<CompiledFunction> | |||
compileIR(std::unique_ptr<IRFunction> IR) const override; | |||
|
|||
std::unique_ptr<CompiledFunction> | |||
compileIRWithoutConstants(IRFunction *IR) const; |
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.
vertical space b/w top level declarations.
std::unique_ptr<CompiledFunction> compile(Function *F) const override; | ||
std::unique_ptr<CompiledFunction> |
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.
vertical space b/w top level declarations.
lib/Backends/CPU/CPUFunction.h
Outdated
/// Base address for Activations memory block. | ||
uint8_t *baseActivationsAddress_{}; | ||
/// Base address for Mutable weights memory block, Inputs and Outputs. | ||
uint8_t *baseMutableWeightVarsAddress_{}; | ||
|
||
public: | ||
/// runtimeBundle contains symbol offsets and allocation sizes. | ||
runtime::RuntimeBundle runtimeBundle_; |
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 recommend keeping runtimeBundle private; having public data members has a way of bloating the API. It seems like you should be able to just add a collectConstants
method to CPUFunction
. (Or maybe even to the CompiledFunction
interface, since it's used by every backend.)
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.
Or maybe even to the CompiledFunction interface, since it's used by every backend.
this way we'd also avoid ugly static_casts on pointers to specific CompiledFunctions.
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 think adding it as a method to each compiledFunction makes sense, I think eventually this will go away entirely, the new DeviceManager will have the collection logic. Unfortunately even if I added it to CompiledFunction OpenCL and Interpreter will still require a static_cast to get the IR.
So how about I keep bundle private and add a new method to each CPUFunction, OpenCLFunction, and InterpreterFunction but not to compiledFunction, since ultimately we'd want to move this to the DeviceManager anyway?
Interpreter::compileWithoutConstants(Function *F) const { | ||
auto IR = generateAndOptimizeIR(F, shouldShareBuffers()); | ||
return compileIRWithoutConstants(std::move(IR)); | ||
} |
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.
Blank line between definitions.
|
||
std::unique_ptr<CompiledFunction> compile(Function *F) const override; | ||
std::unique_ptr<CompiledFunction> |
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.
More blank lines plz :)
@@ -74,6 +74,8 @@ class InterpreterFunction final : public CompiledFunction { | |||
void tearDownRuns() override; | |||
|
|||
void execute() override; | |||
/// Get reference to IR function. | |||
IRFunction *getIR() { return F_.get(); } |
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.
As above, I think adding a collectConstants
would be better than adding getIR
just to pass it back to runtime bundle.
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.
The challenge here is the CPUFunction, it doesn't keep the IR around so it would still need it passed in.
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.
That is a good point. Which makes me wonder, how could we even use collectConstants
with the CPU backend? Since compileIR
takes ownership of the IR and then destroys it, how can we later pass it to collect? (Right now we only collect inside the compile function, but that's going to change soon... right?
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.
Yes, the device manager will have a reference to the module so that is where it can collect constants from.
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.
Looking at collectConstants, does it even need to take an IRFunction? It looks like it pulls all the constants from the Module via F->getGraph()->getParent()->getConstants()
. It then uses getWeightForNode
to turn those back into WeightVars but I don't see a reason for that, since all we do is call getSizeInBytes
, which we can get without getting the WeightVar. Am I missing something?
lib/Backends/BackendUtils.cpp
Outdated
@@ -143,6 +143,5 @@ glow::generateRuntimeBundle(const IRFunction &F, | |||
|
|||
runtime::RuntimeBundle info(symbolTable, constantMaxSize, placeholderMaxSize, |
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.
nit: just return this right away
lib/Backends/CPU/CPUFunction.h
Outdated
/// Base address for Activations memory block. | ||
uint8_t *baseActivationsAddress_{}; | ||
/// Base address for Mutable weights memory block, Inputs and Outputs. | ||
uint8_t *baseMutableWeightVarsAddress_{}; | ||
|
||
public: | ||
/// runtimeBundle contains symbol offsets and allocation sizes. | ||
runtime::RuntimeBundle runtimeBundle_; |
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.
Or maybe even to the CompiledFunction interface, since it's used by every backend.
this way we'd also avoid ugly static_casts on pointers to specific CompiledFunctions.
@@ -42,6 +42,9 @@ class Backend { | |||
|
|||
/// Generate code for input function \param F. | |||
virtual std::unique_ptr<CompiledFunction> compile(Function *F) const = 0; | |||
/// Generate code for input function \param F but do not collect constants. | |||
virtual std::unique_ptr<CompiledFunction> | |||
compileWithoutConstants(Function *F) const = 0; |
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.
where is it invoked?
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.
Currently nowhere but it will be called from the Provisioner.
std::unique_ptr<CompiledFunction> | ||
CPUBackend::compileWithoutConstants(Function *F) const { | ||
auto IR = generateAndOptimizeIR(F, shouldShareBuffers()); | ||
return compileIRWithoutConstants(IR.get()); |
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.
Did we come to a conclusion about how collectConstants
is going to work for the CPU backend yesterday? Since compileWithoutConstants
throws away the IR, we don't have anything to pass to collectConstants
...
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 think we decided to make expose collect constants as a method on each compiled function, and keep the bundle_ private. We call collectConstants in CompileIR where we still have the IR.
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, lgtm!
31823b0
to
983b943
Compare
… Interpreter Backends. This will allow for compilation of the function and collection of the constants to be seperated which is needed for the new Runtime design Added unittest for compileWithoutConstants
c06d3ba
to
488803e
Compare
Description: For the new runtime we need to be able to compile a function but collect the constants slightly later in the initialization process. This PR introduces a compileWithoutConstants method to the backend and updates existing backends to support it.
Testing: passes all unit tests.
Documentation: N/A
Fixes: #2254