Skip to content

Commit 32eb209

Browse files
committed
[Placeholder] Allow executing Placeholders in the execution engine.
Implement the logic for executing Placeholders in the execution engine. This commit changes the backend interface and adds the ability to pass Placeholder variables in addition to Variables. This change breaks the out-of-tree backends. This is the first step in adding support for placeholder variables in the execution engine. The commit adds support to the interpreter but not to the OpenCL and CPU backends.
1 parent b354f24 commit 32eb209

16 files changed

+83
-25
lines changed

include/glow/Backends/Backend.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@ class Backend {
3939
/// Dtor.
4040
virtual ~Backend() = default;
4141

42-
/// Generate code for input function \param IR.
42+
/// Generate code for input function \param IR. \p placeholders is a list of
43+
/// Placeholders that are mapped to the concrete input tensor for the
44+
/// specific function.
4345
virtual std::unique_ptr<CompiledFunction>
44-
compile(std::unique_ptr<IRFunction> IR) const = 0;
46+
compile(std::unique_ptr<IRFunction> IR,
47+
const PlaceholderMap &placeholders) const = 0;
4548

4649
/// Save the bundle for \p IR for a later standalone execution
4750
/// in \p outputDir. Make \p networkName the function name for

include/glow/Backends/CompiledFunction.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@
1616
#ifndef GLOW_BACKENDS_COMPILEDFUNCTION_H
1717
#define GLOW_BACKENDS_COMPILEDFUNCTION_H
1818

19+
#include <unordered_map>
20+
1921
namespace glow {
2022

23+
class Placeholder;
24+
class Tensor;
25+
26+
/// Maps placeholders to the tensors that back them.
27+
using PlaceholderMap = std::unordered_map<Placeholder *, Tensor *>;
28+
2129
/// Interface for executing a compiled function.
2230
class CompiledFunction {
2331
public:

include/glow/ExecutionEngine/ExecutionEngine.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,11 @@ class ExecutionEngine final {
6767

6868
/// Optimize the graph, generate IR, optimize IR and compile it for a
6969
/// specific target. This method should be invoked before the run method.
70-
void compile(CompilationMode mode, Function *F);
70+
/// The placeholder variables in \p placeholders are mapped to the concrete
71+
/// tensor values in the compiled instance of the function.
72+
void compile(CompilationMode mode, Function *F,
73+
llvm::ArrayRef<Placeholder *> placeholders = {},
74+
llvm::ArrayRef<Tensor *> inputs = {});
7175

7276
/// Save a bundle for a standalone execution. This method takes care of
7377
/// everything when preparing the bundle for saving. There is no need to

lib/Backends/CPU/CPUBackend.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ CPUBackend::createIRGen(IRFunction *IR,
123123
}
124124

125125
std::unique_ptr<CompiledFunction>
126-
CPUBackend::compile(std::unique_ptr<IRFunction> IR) const {
126+
CPUBackend::compile(std::unique_ptr<IRFunction> IR,
127+
const PlaceholderMap &placeholders) const {
127128
AllocationsInfo allocationsInfo;
128129
std::unique_ptr<LLVMIRGen> irgen = createIRGen(IR.get(), allocationsInfo);
129130
irgen->initTargetMachine(target.empty() ? "" : target.getValue(),

lib/Backends/CPU/CPUBackend.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class CPUBackend : public Backend {
4343
~CPUBackend() override = default;
4444

4545
std::unique_ptr<CompiledFunction>
46-
compile(std::unique_ptr<IRFunction> IR) const override;
46+
compile(std::unique_ptr<IRFunction> IR,
47+
const PlaceholderMap &placeholders) const override;
4748

4849
void save(std::unique_ptr<IRFunction> IR, llvm::StringRef outputDir,
4950
llvm::StringRef networkName) const override;

lib/Backends/Interpreter/Interpreter.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
using namespace glow;
2525

2626
std::unique_ptr<CompiledFunction>
27-
Interpreter::compile(std::unique_ptr<IRFunction> IR) const {
28-
return llvm::make_unique<InterpreterFunction>(std::move(IR));
27+
Interpreter::compile(std::unique_ptr<IRFunction> IR,
28+
const PlaceholderMap &placeholders) const {
29+
return llvm::make_unique<InterpreterFunction>(std::move(IR), placeholders);
2930
}
3031

3132
bool Interpreter::isOpSupported(Kinded::Kind opKind, ElemKind elementTy) const {

lib/Backends/Interpreter/Interpreter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class Interpreter final : public Backend {
3535
~Interpreter() override = default;
3636

3737
std::unique_ptr<CompiledFunction>
38-
compile(std::unique_ptr<IRFunction> IR) const override;
38+
compile(std::unique_ptr<IRFunction> IR,
39+
const PlaceholderMap &placeholders) const override;
3940

4041
bool isOpSupported(Kinded::Kind opKind, ElemKind elementTy) const override;
4142

lib/Backends/Interpreter/InterpreterFunction.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,22 @@
2424

2525
using namespace glow;
2626

27-
InterpreterFunction::InterpreterFunction(std::unique_ptr<IRFunction> F)
27+
InterpreterFunction::InterpreterFunction(std::unique_ptr<IRFunction> F,
28+
const PlaceholderMap &placeholders)
2829
: F_(std::move(F)) {
30+
31+
// Register the concrete tensors that back the placeholder tensors.
32+
for (auto &ph : placeholders) {
33+
auto *w = F_->getWeightForNode(ph.first);
34+
assert(!externalTensors_.count(w) && "The tensor is already registered");
35+
externalTensors_[w] = ph.second;
36+
}
37+
2938
for (auto &v : F_->getGraph()->getParent()->getVars()) {
3039
auto *w = F_->getWeightForNode(v);
3140
assert(!externalTensors_.count(w) && "The tensor is already registered");
3241
externalTensors_[w] = &v->getPayload();
3342
}
34-
35-
for (auto *W : F_->getWeights()) {
36-
getOrCreateTensor(W);
37-
}
3843
}
3944

4045
InterpreterFunction::~InterpreterFunction() {

lib/Backends/Interpreter/InterpreterFunction.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ class InterpreterFunction final : public CompiledFunction {
4848
std::unordered_map<const Value *, Tensor *> externalTensors_;
4949

5050
public:
51-
InterpreterFunction(std::unique_ptr<IRFunction> F);
51+
InterpreterFunction(std::unique_ptr<IRFunction> F,
52+
const PlaceholderMap &placeholders);
5253

5354
/// \name CompiledFunction interface
5455
///@{

lib/Backends/OpenCL/OpenCL.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,7 @@ cl_mem OpenCLFunction::allocDeviceBuffer(uint64_t size) {
15711571
void OpenCLFunction::freeDeviceBuffer(cl_mem buf) { clReleaseMemObject(buf); }
15721572

15731573
std::unique_ptr<CompiledFunction>
1574-
OCLBackend::compile(std::unique_ptr<IRFunction> IR) const {
1574+
OCLBackend::compile(std::unique_ptr<IRFunction> IR,
1575+
const PlaceholderMap &placeholders) const {
15751576
return llvm::make_unique<OpenCLFunction>(std::move(IR));
15761577
}

lib/Backends/OpenCL/OpenCL.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ class OCLBackend final : public Backend {
171171
~OCLBackend() override = default;
172172

173173
std::unique_ptr<CompiledFunction>
174-
compile(std::unique_ptr<IRFunction> IR) const override;
174+
compile(std::unique_ptr<IRFunction> IR,
175+
const PlaceholderMap &placeholders) const override;
175176

176177
bool transformPostLowering(Function *F, CompilationMode mode) const override;
177178

lib/ExecutionEngine/ExecutionEngine.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,19 @@ std::unique_ptr<IRFunction> ExecutionEngine::generateIR(CompilationMode mode,
169169
return IR;
170170
}
171171

172-
void ExecutionEngine::compile(CompilationMode mode, Function *F) {
173-
function_ = backend_->compile(generateIR(mode, F));
172+
void ExecutionEngine::compile(CompilationMode mode, Function *F,
173+
llvm::ArrayRef<Placeholder *> placeholders,
174+
llvm::ArrayRef<Tensor *> inputs) {
175+
PlaceholderMap pmap;
176+
assert(placeholders.size() == inputs.size() &&
177+
"Invalid number of placeholders");
178+
179+
for (size_t i = 0, e = placeholders.size(); i < e; i++) {
180+
pmap[placeholders[i]] = inputs[i];
181+
}
182+
183+
auto IR = generateIR(mode, F);
184+
function_ = backend_->compile(std::move(IR), pmap);
174185
}
175186

176187
void ExecutionEngine::save(CompilationMode mode, Function *F,

tests/unittests/BackendCorrectnessTest.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,9 @@ class MockCPUBackend : public Backend {
239239
public:
240240
MockCPUBackend() { backend_.reset(createBackend(BackendKind::CPU)); }
241241
std::unique_ptr<CompiledFunction>
242-
compile(std::unique_ptr<IRFunction> IR) const override {
243-
return backend_->compile(std::move(IR));
242+
compile(std::unique_ptr<IRFunction> IR,
243+
const PlaceholderMap &placeholders) const override {
244+
return backend_->compile(std::move(IR), placeholders);
244245
}
245246
bool isOpSupported(Kinded::Kind opKind, ElemKind elementTy) const override {
246247
return true;
@@ -304,7 +305,8 @@ TEST_P(CPUOnly, dataParallelStackingTest) {
304305
}
305306

306307
MockCPUBackend backend;
307-
backend.compile(std::move(M))->execute();
308+
PlaceholderMap empty;
309+
backend.compile(std::move(M), empty)->execute();
308310
auto H = var->getHandle();
309311
EXPECT_EQ(H.at(0), 3);
310312
EXPECT_EQ(H.at(1), 4);

tests/unittests/BackendTest.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ TEST_P(BackendTest, debugPrint) {
145145
IRBuilder(IR.get()).createDebugPrintInst("print", *IR->getWeights().begin());
146146

147147
std::unique_ptr<Backend> backend(createBackend(GetParam()));
148-
auto function = backend->compile(std::move(IR));
148+
PlaceholderMap empty;
149+
auto function = backend->compile(std::move(IR), empty);
149150
function->execute();
150151
}
151152

@@ -176,6 +177,21 @@ TEST_P(BackendTest, decoupleCodegenFromGraph) {
176177
EXPECT_NEAR(HX.at({2}), 9, 1E-5);
177178
}
178179

180+
/// Check that we can pass information to the execution engine using Placeholder
181+
/// variables and read it back using Save nodes (in variables).
182+
TEST(Placeholder, simplePlaceholderValue) {
183+
Tensor data{99.0, 35.0, 2.0, 3.0};
184+
ExecutionEngine EE{BackendKind::Interpreter};
185+
auto &mod = EE.getModule();
186+
Function *F = mod.createFunction("main");
187+
auto *input = mod.createPlaceholder(ElemKind::FloatTy, {4}, "input");
188+
SaveNode *S = F->createSave("ret", input);
189+
EE.compile(CompilationMode::Infer, F, {input}, {&data});
190+
EE.run();
191+
auto &res = S->getVariable()->getPayload();
192+
EXPECT_TRUE(res.isEqual(data));
193+
}
194+
179195
INSTANTIATE_TEST_CASE_P(Interpreter, BackendTest,
180196
::testing::Values(BackendKind::Interpreter));
181197

tests/unittests/BackendTestUtils.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ class MockBackend : public Backend {
2626
void execute() override {}
2727
};
2828
std::unique_ptr<CompiledFunction>
29-
compile(std::unique_ptr<IRFunction> IR) const override {
29+
compile(std::unique_ptr<IRFunction> IR,
30+
const PlaceholderMap &placeholders) const override {
3031
return llvm::make_unique<MockFunction>();
3132
}
3233
bool isOpSupported(Kinded::Kind opKind, ElemKind elementTy) const override {

tests/unittests/quantizationTest.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -615,8 +615,9 @@ class MockQuantBackend : public Backend {
615615
backend_.reset(createBackend(BackendKind::Interpreter));
616616
}
617617
std::unique_ptr<CompiledFunction>
618-
compile(std::unique_ptr<IRFunction> IR) const override {
619-
return backend_->compile(std::move(IR));
618+
compile(std::unique_ptr<IRFunction> IR,
619+
const PlaceholderMap &placeholders) const override {
620+
return backend_->compile(std::move(IR), placeholders);
620621
}
621622
bool isOpSupported(Kinded::Kind opKind, ElemKind elementTy) const override {
622623
if (opKind == Kinded::Kind::SoftMaxNodeKind ||

0 commit comments

Comments
 (0)