Skip to content

ExecutionEngine #32

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 5 commits into from
Oct 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ target_link_libraries(cifar10
PRIVATE
Interpreter
Network
ExecutionEngine
Graph
IR
Support)
Expand All @@ -15,6 +16,7 @@ target_link_libraries(mnist
PRIVATE
Interpreter
Network
ExecutionEngine
Graph
IR
Support)
Expand Down
34 changes: 12 additions & 22 deletions examples/cifar10.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
#include "glow/ExecutionEngine/ExecutionEngine.h"
#include "glow/Graph/Graph.h"
#include "glow/Graph/Nodes.h"
#include "glow/IR/IR.h"
#include "glow/IR/IRBuilder.h"
#include "glow/IR/Instrs.h"
#include "glow/Interpreter/Interpreter.h"
#include "glow/Support/Support.h"

#include "llvm/Support/Timer.h"

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <iterator>
#include <random>
#include <string>
#include <vector>

using namespace glow;

Expand Down Expand Up @@ -67,14 +57,14 @@ void testCIFAR10() {
GLOW_ASSERT(idx == cifarImageSize * cifarNumImages && "Invalid input file");

// Construct the network:
Interpreter IP;
IP.getConfig().learningRate = 0.001;
IP.getConfig().momentum = 0.9;
IP.getConfig().L2Decay = 0.0001;
ExecutionEngine EE;
EE.getConfig().learningRate = 0.001;
EE.getConfig().momentum = 0.9;
EE.getConfig().L2Decay = 0.0001;

unsigned minibatchSize = 8;

auto &G = IP.getGraph();
auto &G = EE.getGraph();

// Create the input layer:
auto *A =
Expand All @@ -100,9 +90,9 @@ void testCIFAR10() {
auto *SM = G.createSoftMax("softmax", RL3, E);
auto *result = G.createReturn("ret", SM);

IP.getModule().generateIR();
IP.optimize(OptimizationMode::Train);
IP.initVars();
EE.generateIR();
EE.optimize(OptimizationMode::Train);
EE.initVars();

// Report progress every this number of training iterations.
int reportRate = 256;
Expand All @@ -117,15 +107,15 @@ void testCIFAR10() {

// Bind the images tensor to the input array A, and the labels tensor
// to the softmax node SM.
IP.train(reportRate, {A, E}, {&images, &labels});
EE.train(reportRate, {A, E}, {&images, &labels});

unsigned score = 0;

for (unsigned int i = 0; i < 100 / minibatchSize; i++) {
Tensor sample(ElemKind::FloatTy, {minibatchSize, 3, 32, 32});
sample.copyConsecutiveSlices(&images, minibatchSize * i);
IP.infer({A}, {&sample});
auto *res = IP.getTensorForNode(result);
EE.infer({A}, {&sample});
auto *res = EE.getTensor(result);

for (unsigned int iter = 0; iter < minibatchSize; iter++) {
auto T = res->getHandle<FloatTy>().extractSlice(iter);
Expand Down
36 changes: 14 additions & 22 deletions examples/mnist.cpp
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
#include "glow/ExecutionEngine/ExecutionEngine.h"
#include "glow/Graph/Graph.h"
#include "glow/Graph/Node.h"
#include "glow/Graph/Nodes.h"
#include "glow/IR/IR.h"
#include "glow/IR/IRBuilder.h"
#include "glow/IR/Instrs.h"
#include "glow/Interpreter/Interpreter.h"
#include "glow/Support/Support.h"

#include "llvm/Support/Timer.h"

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

using namespace glow;

Expand Down Expand Up @@ -69,13 +60,14 @@ void testMNIST() {

unsigned minibatchSize = 8;

ExecutionEngine EE;

// Construct the network:
Interpreter IP;
IP.getConfig().learningRate = 0.001;
IP.getConfig().momentum = 0.9;
IP.getConfig().L2Decay = 0.001;
EE.getConfig().learningRate = 0.001;
EE.getConfig().momentum = 0.9;
EE.getConfig().L2Decay = 0.001;

auto &G = IP.getGraph();
auto &G = EE.getGraph();

Variable *A = G.createVariable(ElemKind::FloatTy, {minibatchSize, 28, 28, 1},
"input", Variable::InitKind::Extern);
Expand All @@ -97,9 +89,9 @@ void testMNIST() {

auto *result = G.createReturn("return", SM);

IP.getModule().generateIR();
IP.optimize(OptimizationMode::Train);
IP.initVars();
EE.generateIR();
EE.optimize(OptimizationMode::Train);
EE.initVars();

// Report progress every this number of training iterations.
constexpr int reportRate = 30;
Expand All @@ -115,12 +107,12 @@ void testMNIST() {
// On each training iteration take an input from imageInputs and update
// the input variable A, and add take a corresponding label and update the
// softmax layer.
IP.train(reportRate, {A, selected}, {&imageInputs, &labelInputs});
EE.train(reportRate, {A, selected}, {&imageInputs, &labelInputs});

timer.stopTimer();
}
std::cout << "Validating.\n";
IP.optimize(OptimizationMode::Infer);
EE.optimize(OptimizationMode::Infer);

auto LIH = labelInputs.getHandle<size_t>();

Expand All @@ -129,8 +121,8 @@ void testMNIST() {

Tensor sample(ElemKind::FloatTy, {minibatchSize, 1, 28, 28});
sample.copyConsecutiveSlices(&imageInputs, 0);
IP.infer({A}, {&sample});
Tensor *res = IP.getTensorForNode(result);
EE.infer({A}, {&sample});
Tensor *res = EE.getTensor(result);

for (unsigned int iter = 0; iter < minibatchSize; iter++) {
auto T = res->getHandle<FloatTy>().extractSlice(iter);
Expand Down
10 changes: 5 additions & 5 deletions include/glow/Base/Tensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,20 +112,20 @@ class Tensor final {
Tensor() = default;

/// Initialize from a list of float literals.
Tensor(const std::initializer_list<double> &vec) : type_{} {
Tensor(const std::initializer_list<double> &vec) {
reset(ElemKind::FloatTy, {vec.size()});
FloatTy *data = getRawDataPointer<FloatTy>();
auto *data = getRawDataPointer<FloatTy>();
int i = 0;
for (auto &f : vec) {
data[i++] = f;
}
}

/// Allocate and initialize a new tensor.
Tensor(TypeRef ty) : data_(nullptr), type_(*ty) { reset(*ty); }
explicit Tensor(TypeRef ty) : data_(nullptr), type_(*ty) { reset(*ty); }

/// Allocate and initialize a new tensor.
Tensor(const Type &ty) : data_(nullptr), type_(ty) { reset(ty); }
explicit Tensor(const Type &ty) : data_(nullptr), type_(ty) { reset(ty); }

/// Allocate and initialize a new tensor.
Tensor(ElemKind elemTy, llvm::ArrayRef<size_t> dims)
Expand Down Expand Up @@ -320,7 +320,7 @@ template <class ElemTy> class Handle final {
}

void clear(ElemTy value = 0) {
ElemTy *data = tensor_->getRawDataPointer<ElemTy>();
auto *data = tensor_->getRawDataPointer<ElemTy>();
std::fill(&data[0], &data[0] + size(), value);
}

Expand Down
8 changes: 4 additions & 4 deletions include/glow/IR/Traits.h → include/glow/Base/Traits.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef GLOW_IR_TRAITS_H
#define GLOW_IR_TRAITS_H
#ifndef GLOW_BASE_TRAITS_H
#define GLOW_BASE_TRAITS_H

#include "glow/Base/Type.h"

Expand Down Expand Up @@ -31,7 +31,7 @@ class Typed {
TypeRef Ty_{};

public:
Typed(TypeRef Ty) : Ty_(Ty){};
explicit Typed(TypeRef Ty) : Ty_(Ty){};

TypeRef getType() const { return Ty_; }

Expand Down Expand Up @@ -78,4 +78,4 @@ class Kinded {

} // namespace glow

#endif // GLOW_IR_TRAITS_H
#endif // GLOW_BASE_TRAITS_H
99 changes: 99 additions & 0 deletions include/glow/ExecutionEngine/ExecutionEngine.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#ifndef GLOW_EXECUTIONENGINE_EXECUTIONENGINE_H
#define GLOW_EXECUTIONENGINE_EXECUTIONENGINE_H

#include "glow/Base/Train.h"
#include "glow/Optimizer/Optimizer.h"

#include "llvm/ADT/ArrayRef.h"

#include <memory>
#include <unordered_map>

namespace glow {

class Graph;
class Node;
class Interpreter;
class Variable;
class Tensor;
class Value;

/// This is the ExecutionEngine. It owns the Graph, the IR, and the backends.
/// The Graph, Module, etc in this class are defined as pointers, in order to
/// erase the type and prevent the internal types from leaking out to the
/// users of this class.
class ExecutionEngine final {
/// The Graph that represents the high-level program.
Graph *G_;
/// The Module that holds the IR.
Module *M_;
/// The network interpreter
Interpreter *IP_;
/// The network trainer.
Trainer trainer_{};

public:
ExecutionEngine();

~ExecutionEngine();

/// \returns the internal module.
Module &getModule() { return *M_; }

/// \returns the internal module.
Graph &getGraph() { return *G_; }

/// Run the target-independent optimizations on the module.
void optimize(OptimizationMode mode);

/// Generate IR from the graph nodes.
void generateIR();

/// Provides access to the training configuration.
TrainingConfig &getConfig() { return trainer_.config; }

/// Initialize all of the variables in the program.
void initVars();

/// Runs the program in a forward pass. Update the nodes in \p nodes with the
/// values \p inputs.
void infer(llvm::ArrayRef<Variable *> vars, llvm::ArrayRef<Tensor *> inputs);

/// Train the network. Perform \p iterations in the training loop. Each
/// iteration does a full forward and backward pass of a whole batch.
/// The method updates the variables in \p vars with the tensors \p inputs.
void train(size_t iterations, llvm::ArrayRef<Variable *> vars,
llvm::ArrayRef<Tensor *> inputs);

/// \returns a pointer to the tensor that is saved under \p v. The tensor
/// is owned by the Interpreter.
Tensor *getTensor(const Node *v) const;

/// \returns a float-handle to the tensor that is stored at \p v.
Handle<FloatTy> getWeightHandle(Variable *v) const;

/// \returns a float-handle to the tensor that is stored at \p v.
Handle<FloatTy> getGradHandle(Variable *v);

/// Copies the content of the tensor \p t into the value \p v.
void initValue(const Variable *v, const Tensor *t);

private:
/// Update the inputs for all variables \p vars with data from the inputs \p
/// inputs at offset \p sampleIdx. Then perform a forward and backwards scan.
void updateForwardBackward(llvm::ArrayRef<Value *> vars,
llvm::ArrayRef<Tensor *> inputs, size_t sampleIdx);

/// Update all of the weight tensors (non-activation) with their gradients.
void learnGradient(size_t batchSize);

/// Update the content of the tensor \p v with data that comes from \p input.
/// The data starts at slice \p sampleIdx and wraps around until the data in
/// \p v is filled. All dimensions, except for the first (batch) dimension
/// must be identical.
void loadValueFromTensor(const Value *v, Tensor *input, size_t sampleIdx);
};

} // namespace glow

#endif // GLOW_EXECUTIONENGINE_EXECUTIONENGINE_H
18 changes: 0 additions & 18 deletions include/glow/Graph/Graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,6 @@

namespace glow {

class Node;
class Variable;
class ConvolutionNode;
class PoolNode;
class FullyConnectedNode;
class ReluNode;
class SigmoidNode;
class TanhNode;
class SoftMaxNode;
class RegressionNode;
class ReshapeNode;
class TransposeNode;
class ConcatNode;
class BatchNormalizationNode;
class LocalResponseNormalizationNode;
class ArithmeticNode;
class ReturnNode;

/// Represents the compute graph.
class Graph final {
/// A uniqued list of types in the module. Types in this list can be compared
Expand Down
2 changes: 1 addition & 1 deletion include/glow/Graph/Node.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

#include "llvm/ADT/StringRef.h"

#include "glow/Base/Traits.h"
#include "glow/Base/Type.h"
#include "glow/IR/Traits.h"

namespace glow {

Expand Down
Loading