Skip to content

Commit 2ceff6b

Browse files
committed
[Placeholder] Teach the OCL and CPU backends to handle Placeholders.
1 parent 4dd7052 commit 2ceff6b

File tree

7 files changed

+61
-19
lines changed

7 files changed

+61
-19
lines changed

lib/Backends/CPU/AllocationsInfo.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ using llvm::dyn_cast;
3232
using llvm::isa;
3333

3434
void AllocationsInfo::allocateWeightVars(const IRFunction *F,
35+
const PlaceholderMap &placeholders,
3536
bool absoluteAddr) {
3637
// Use two different allocators, because constant weights and mutable weights
3738
// may use different memory blocks.
@@ -73,6 +74,21 @@ void AllocationsInfo::allocateWeightVars(const IRFunction *F,
7374
}
7475
}
7576

77+
// Allocate addresses for the Placeholders.
78+
for (auto PH : placeholders) {
79+
assert(isa<WeightVar>(F->getWeightForNode(PH.first)));
80+
auto *w = cast<WeightVar>(F->getWeightForNode(PH.first));
81+
auto numBytes = w->getSizeInBytes();
82+
size_t addr = mutableWeightVarsAllocator.allocate(numBytes, w);
83+
if (!absoluteAddr) {
84+
allocatedAddressed_[w] = addr;
85+
} else {
86+
// Reuse the address used by the payload.
87+
allocatedAddressed_[w] =
88+
PH.second->getUnsafePtr() - static_cast<char *>(nullptr);
89+
}
90+
}
91+
7692
// Remember that max required memory size for each kind of weights.
7793
constantWeightVarsMemSize_ = constantWeightVarsAllocator.getMaxMemoryUsage();
7894
mutableWeightVarsMemSize_ = mutableWeightVarsAllocator.getMaxMemoryUsage();
@@ -196,6 +212,14 @@ void AllocationsInfo::numberValues(const IRFunction *F) {
196212
: ValueKind::MutableWeight;
197213
valueNumbers_[w] = std::make_pair(kind, valueIdx++);
198214
}
215+
216+
// Assign numbers to all placeholders.
217+
for (auto &v : F->getGraph()->getParent()->getPlaceholders()) {
218+
assert(isa<WeightVar>(F->getWeightForNode(v)));
219+
auto *w = cast<WeightVar>(F->getWeightForNode(v));
220+
valueNumbers_[w] = std::make_pair(ValueKind::MutableWeight, valueIdx++);
221+
}
222+
199223
// Assign numbers to all activations and tensorviews.
200224
for (const auto &I : F->getInstrs()) {
201225
if (auto *A = dyn_cast<AllocActivationInst>(&I)) {

lib/Backends/CPU/AllocationsInfo.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
#ifndef GLOW_BACKENDS_CPU_ALLOCATIONSINFO_H
1717
#define GLOW_BACKENDS_CPU_ALLOCATIONSINFO_H
1818

19+
#include "glow/Backends/CompiledFunction.h"
20+
1921
#include "llvm/IR/Module.h"
2022

2123
#include <functional>
@@ -52,12 +54,15 @@ struct AllocationsInfo {
5254
/// Base address of activations.
5355
uint8_t *baseActivationsAddress_{nullptr};
5456

55-
/// Assign offsets to all WeightVars of \p M.
57+
/// Assign offsets to all of the variables in the module \p M and to the
58+
/// placeholders \p placeholders.
5659
/// If the \p absoluteAddr is true, simply reuse the addresses already used
5760
/// by the payloads of tensors corresponding to those WeightVars as offsets.
5861
/// This is useful in a JIT setup. If \p absoluteAddr is false, then all the
5962
/// WeightVars will get new offsets assigned.
60-
void allocateWeightVars(const IRFunction *F, bool absoluteAddr);
63+
void allocateWeightVars(const IRFunction *F,
64+
const PlaceholderMap &placeholders,
65+
bool absoluteAddr);
6166
/// Assign offsets to all activations.
6267
/// No actual memory allocation is performed. All the allocations should be
6368
/// performed by the client based on the information provided by the

lib/Backends/CPU/BundleSaver.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ void BundleSaver::performBundleMemoryAllocation() {
250250
allocationsInfo_.allocateActivations(F_);
251251
// Tell the allocateWeightVars to not reuse any existing addresses for weights
252252
// and to assign new ones.
253-
allocationsInfo_.allocateWeightVars(F_, false);
253+
PlaceholderMap empty;
254+
allocationsInfo_.allocateWeightVars(F_, empty, false);
254255
allocationsInfo_.allocateTensorViews(F_);
255256
}
256257

lib/Backends/CPU/CPUBackend.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,12 @@ static void emitJitMain(LLVMIRGen &irgen) {
9696

9797
/// Perform memory allocation for a JIT execution.
9898
static void *allocateJITMemory(const IRFunction *F,
99-
AllocationsInfo &allocationsInfo) {
99+
AllocationsInfo &allocationsInfo,
100+
const PlaceholderMap &placeholders) {
100101
allocationsInfo.numberValues(F);
101102
allocationsInfo.allocateActivations(F);
102-
// Tell the allocateWeightVars to reuse existing addresses for weights.
103-
allocationsInfo.allocateWeightVars(F, true);
103+
// Tell the allocateWeightVars to use absolute addresses for weights.
104+
allocationsInfo.allocateWeightVars(F, placeholders, true);
104105
allocationsInfo.allocateTensorViews(F);
105106

106107
// Allocate the heap to match the max memory usage for activations.
@@ -131,7 +132,8 @@ CPUBackend::compile(std::unique_ptr<IRFunction> IR,
131132
llvm::CodeModel::Model::Large);
132133
irgen->initCodeGen();
133134
// Perform the address assignment for activations and WeightVars.
134-
auto heap = allocateJITMemory(IR.get(), irgen->getAllocationsInfo());
135+
auto heap =
136+
allocateJITMemory(IR.get(), irgen->getAllocationsInfo(), placeholders);
135137
// Create the jitmain function to be invoked by JIT.
136138
emitJitMain(*irgen);
137139
// Emit the code for the body of the entry function.

lib/Backends/OpenCL/OpenCL.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ static void addStringOption(std::vector<std::string> &options,
9898
options.push_back("-D" + name + "=" + value);
9999
}
100100

101-
OpenCLFunction::OpenCLFunction(std::unique_ptr<IRFunction> F)
101+
OpenCLFunction::OpenCLFunction(std::unique_ptr<IRFunction> F,
102+
const PlaceholderMap &placeholders)
102103
: F_(std::move(F)) {
103104
cl_uint numPlatforms{0};
104105
cl_int err = clGetPlatformIDs(0, NULL, &numPlatforms);
@@ -136,7 +137,7 @@ OpenCLFunction::OpenCLFunction(std::unique_ptr<IRFunction> F)
136137
addIntOption(options, "SIZEOF_HOST_SIZE_T", sizeof(size_t));
137138
// Create the program from the source.
138139
createProgram(SHADER_CODE, options, commands_);
139-
allocateMemory();
140+
allocateMemory(placeholders);
140141
}
141142

142143
OpenCLFunction::~OpenCLFunction() {
@@ -1482,15 +1483,24 @@ uint64_t OpenCLFunction::copyMutableWeightsFromDevice() {
14821483
return copiedBytes;
14831484
}
14841485

1485-
void OpenCLFunction::allocateMemory() {
1486-
/// The allocator assigns device memory addresses to the buffers.
1486+
void OpenCLFunction::allocateMemory(const PlaceholderMap &placeholders) {
1487+
// The allocator assigns device memory addresses to the buffers.
14871488
MemoryAllocator allocator("GPU", 0xFFFFFFFF);
1489+
1490+
// Register the bound locations of the variables.
14881491
for (auto &v : F_->getGraph()->getParent()->getVars()) {
14891492
auto *w = F_->getWeightForNode(v);
14901493
assert(!externalTensors_.count(w) && "The tensor is already registered");
14911494
externalTensors_[w] = &v->getPayload();
14921495
}
14931496

1497+
// Register the bound locations of the placeholders.
1498+
for (auto PH : placeholders) {
1499+
auto *w = F_->getWeightForNode(PH.first);
1500+
assert(!externalTensors_.count(w) && "The tensor is already registered");
1501+
externalTensors_[w] = PH.second;
1502+
}
1503+
14941504
// Assign device-space addresses to the weights.
14951505
for (auto it : externalTensors_) {
14961506
Tensor *T = it.second;
@@ -1573,5 +1583,5 @@ void OpenCLFunction::freeDeviceBuffer(cl_mem buf) { clReleaseMemObject(buf); }
15731583
std::unique_ptr<CompiledFunction>
15741584
OCLBackend::compile(std::unique_ptr<IRFunction> IR,
15751585
const PlaceholderMap &placeholders) const {
1576-
return llvm::make_unique<OpenCLFunction>(std::move(IR));
1586+
return llvm::make_unique<OpenCLFunction>(std::move(IR), placeholders);
15771587
}

lib/Backends/OpenCL/OpenCL.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ class OpenCLFunction final : public CompiledFunction {
9292

9393
public:
9494
/// Ctor.
95-
explicit OpenCLFunction(std::unique_ptr<IRFunction> F);
95+
explicit OpenCLFunction(std::unique_ptr<IRFunction> F,
96+
const PlaceholderMap &placeholders);
9697

9798
/// @name CompiledFunction interface
9899
///@{
@@ -103,7 +104,7 @@ class OpenCLFunction final : public CompiledFunction {
103104

104105
private:
105106
/// Allocate memory for the tensors.
106-
void allocateMemory();
107+
void allocateMemory(const PlaceholderMap &placeholders);
107108
/// Copy the value from a device to a provided buffer.
108109
/// If \p buf is nullptr, the payload of the underlying tensor is used.
109110
/// \returns number of copied bytes.

tests/unittests/BackendTest.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,14 @@ TEST_P(BackendTest, decoupleCodegenFromGraph) {
179179

180180
/// Check that we can pass information to the execution engine using Placeholder
181181
/// variables and read it back using Save nodes (in variables).
182-
TEST(Placeholder, simplePlaceholderValue) {
182+
TEST_P(BackendTest, simplePlaceholderValue) {
183183
Tensor data{99.0, 35.0, 2.0, 3.0};
184-
ExecutionEngine EE{BackendKind::Interpreter};
185-
auto &mod = EE.getModule();
184+
auto &mod = EE_.getModule();
186185
Function *F = mod.createFunction("main");
187186
auto *input = mod.createPlaceholder(ElemKind::FloatTy, {4}, "input");
188187
SaveNode *S = F->createSave("ret", input);
189-
EE.compile(CompilationMode::Infer, F, {input}, {&data});
190-
EE.run();
188+
EE_.compile(CompilationMode::Infer, F, {input}, {&data});
189+
EE_.run();
191190
auto &res = S->getVariable()->getPayload();
192191
EXPECT_TRUE(res.isEqual(data));
193192
}

0 commit comments

Comments
 (0)