diff --git a/examples/cifar10.cpp b/examples/cifar10.cpp index f851347479..4e9e74df3e 100644 --- a/examples/cifar10.cpp +++ b/examples/cifar10.cpp @@ -100,7 +100,7 @@ void testCIFAR10() { auto *SM = G.createSoftMax("softmax", RL3, E); auto *result = G.createReturn("ret", SM); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); diff --git a/examples/mnist.cpp b/examples/mnist.cpp index 6054949261..259c42d2db 100644 --- a/examples/mnist.cpp +++ b/examples/mnist.cpp @@ -97,7 +97,7 @@ void testMNIST() { auto *result = G.createReturn("return", SM); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); diff --git a/include/glow/Network/Image.h b/include/glow/Base/Image.h similarity index 79% rename from include/glow/Network/Image.h rename to include/glow/Base/Image.h index ba5ffe836b..3ca0fb8395 100644 --- a/include/glow/Network/Image.h +++ b/include/glow/Base/Image.h @@ -1,7 +1,7 @@ -#ifndef GLOW_NETWORK_IMAGE_H -#define GLOW_NETWORK_IMAGE_H +#ifndef GLOW_BASE_IMAGE_H +#define GLOW_BASE_IMAGE_H -#include "glow/Network/Tensor.h" +#include "glow/Base/Tensor.h" namespace glow { @@ -17,4 +17,4 @@ bool writePngImage(Tensor *T, const char *filename, } // namespace glow -#endif // GLOW_NETWORK_IMAGE_H +#endif // GLOW_BASE_IMAGE_H diff --git a/include/glow/Network/Tensor.h b/include/glow/Base/Tensor.h similarity index 98% rename from include/glow/Network/Tensor.h rename to include/glow/Base/Tensor.h index 439d4b440d..5619e9a99a 100644 --- a/include/glow/Network/Tensor.h +++ b/include/glow/Base/Tensor.h @@ -1,9 +1,9 @@ -#ifndef GLOW_NETWORK_TENSOR_H -#define GLOW_NETWORK_TENSOR_H +#ifndef GLOW_BASE_TENSOR_H +#define GLOW_BASE_TENSOR_H #include "Config.h" -#include "glow/IR/Type.h" +#include "glow/Base/Type.h" #include "glow/Support/Compiler.h" #include "glow/Support/Random.h" @@ -328,7 +328,7 @@ template class Handle final { assert(tensor_->isInBounds(indices)); size_t index = getElementPtr(indices); assert(index < size() && "Out of bounds"); - ElemTy *data = tensor_->getRawDataPointer(); + auto *data = tensor_->getRawDataPointer(); return data[index]; } @@ -343,7 +343,7 @@ template class Handle final { /// \returns the element at offset \p idx without any size calculations. ElemTy &raw(size_t index) { assert(index < size() && "Out of bounds"); - ElemTy *data = tensor_->getRawDataPointer(); + auto *data = tensor_->getRawDataPointer(); return data[index]; } @@ -655,4 +655,4 @@ template Handle Tensor::getHandle() { } // namespace glow -#endif // GLOW_NETWORK_TENSOR_H +#endif // GLOW_BASE_TENSOR_H diff --git a/include/glow/Network/Train.h b/include/glow/Base/Train.h similarity index 90% rename from include/glow/Network/Train.h rename to include/glow/Base/Train.h index ccb8952965..bab74cb426 100644 --- a/include/glow/Network/Train.h +++ b/include/glow/Base/Train.h @@ -1,7 +1,7 @@ -#ifndef GLOW_NETWORK_TRAIN_H -#define GLOW_NETWORK_TRAIN_H +#ifndef GLOW_BASE_TRAIN_H +#define GLOW_BASE_TRAIN_H -#include "glow/Network/Tensor.h" +#include "glow/Base/Tensor.h" #include #include @@ -52,4 +52,4 @@ class Trainer { } // namespace glow -#endif // GLOW_NETWORK_TRAIN_H +#endif // GLOW_BASE_TRAIN_H diff --git a/include/glow/IR/Type.h b/include/glow/Base/Type.h similarity index 94% rename from include/glow/IR/Type.h rename to include/glow/Base/Type.h index cc04a7c4c8..2ec7fc4e56 100644 --- a/include/glow/IR/Type.h +++ b/include/glow/Base/Type.h @@ -1,5 +1,5 @@ -#ifndef GLOW_IR_TYPE_H -#define GLOW_IR_TYPE_H +#ifndef GLOW_BASE_TYPE_H +#define GLOW_BASE_TYPE_H #include "glow/Support/Compiler.h" @@ -78,7 +78,7 @@ struct Type final { unsigned char numSizes_{0}; /// Specifies the element type of the tensor. - ElemKind elementType_; + ElemKind elementType_{ElemKind::IndexTy}; /// Initialize a new type. Type(ElemKind elemTy, llvm::ArrayRef dims) : elementType_(elemTy) { @@ -92,7 +92,7 @@ struct Type final { } /// An empty type. - Type() : elementType_(ElemKind::IndexTy) { numSizes_ = 0; } + Type() = default; /// \returns true if \p other is the same type. bool isEqual(TypeRef other) const { return isEqual(*other); } @@ -100,15 +100,18 @@ struct Type final { /// \returns true if \p other is the same type. bool isEqual(const Type &other) const { // Element type must be the same. - if (elementType_ != other.elementType_) + if (elementType_ != other.elementType_) { return false; + } // Must have the same number of sizes. - if (numSizes_ != other.numSizes_) + if (numSizes_ != other.numSizes_) { return false; + } // Sizes must be the same. for (size_t i = 0; i < numSizes_; i++) { - if (sizes_[i] != other.sizes_[i]) + if (sizes_[i] != other.sizes_[i]) { return false; + } } return true; @@ -198,6 +201,6 @@ inline bool operator==(const Type &LHS, const Type &RHS) { namespace std { std::string to_string(const glow::Type &); -} +} // namespace std -#endif // GLOW_IR_TYPE_H +#endif // GLOW_BASE_TYPE_H diff --git a/include/glow/Graph/Graph.h b/include/glow/Graph/Graph.h index 706b3ee7ce..c03a99c334 100644 --- a/include/glow/Graph/Graph.h +++ b/include/glow/Graph/Graph.h @@ -1,10 +1,13 @@ #ifndef GLOW_GRAPH_GRAPH_H #define GLOW_GRAPH_GRAPH_H -#include "glow/IR/Instrs.h" +#include "glow/Base/Type.h" + +#include "glow/Graph/Nodes.h" #include "llvm/ADT/ArrayRef.h" +#include #include #include @@ -30,19 +33,13 @@ class ReturnNode; /// Represents the compute graph. class Graph final { -public: - /// Stores the mapping between graph nodes to IR variables. - using NodeToInstrTy = std::unordered_map; - -private: + /// A uniqued list of types in the module. Types in this list can be compared + /// by comparing their addresses. + std::list types_{}; /// A list of nodes that the graph owns. std::vector nodes_; /// A list of variables that the graph owns. std::vector vars_; - /// A reference to the low-level IR module. - Module &M_; - /// Maps nodes in the graph to the generated IR. - NodeToInstrTy IRMap; /// Inserts the node \p N to the list of nodes, and returns the inserted node. template NodeTy *addNode(NodeTy *N) { @@ -57,26 +54,36 @@ class Graph final { } public: - Graph(Module &M) : M_(M) {} + Graph() = default; + ~Graph(); + /// Return a pointer to a uniqued type \p t in the current module. + TypeRef uniqueType(const Type &T); + + /// Return a pointer to a uniqued type \p t in the current module. + TypeRef uniqueType(ElemKind elemTy, llvm::ArrayRef dims); + + /// Return the void type. + TypeRef getVoidTy(); + /// @name High-level, operation-level IRBuilder. ///@{ Variable * createVariable(TypeRef T, llvm::StringRef name, - WeightVar::InitKind initKind = WeightVar::InitKind::Broadcast, + Variable::InitKind initKind = Variable::InitKind::Broadcast, float val = 0.0); Variable * createVariable(ElemKind T, llvm::ArrayRef dims, llvm::StringRef name, - WeightVar::InitKind initKind = WeightVar::InitKind::Broadcast, + Variable::InitKind initKind = Variable::InitKind::Broadcast, float val = 0.0); ConvolutionNode *createConv(llvm::StringRef name, Node *input, size_t depth, size_t kernel, size_t stride, size_t pad); - PoolNode *createPool(llvm::StringRef name, Node *input, PoolInst::OpKind kind, + PoolNode *createPool(llvm::StringRef name, Node *input, PoolNode::OpKind kind, size_t kernel, size_t stride, size_t pad); FullyConnectedNode *createFullyConnected(llvm::StringRef name, Node *input, @@ -113,27 +120,23 @@ class Graph final { float alpha = 1e-4, float beta = 0.75, float k = 2.0); ArithmeticNode *createArithmetic(llvm::StringRef name, Node *LHS, Node *RHS, - ArithmeticInst::OpKind op); + ArithmeticNode::OpKind op); ReturnNode *createReturn(llvm::StringRef name, Node *input); /// @} - /// Registers the fact that the node \p N was lowered into the IR value \p V. - void registerIRMap(const Node *N, Value *V); - - /// \returns the IR value that the node \p N was lowered into, or null, if the - /// node was not lowered into any IR value. - Value *getIRForNode(const Node *N) const; - - /// Generate IR from the nodes in the graph into the module. - void generateIR(); - /// Dumps the textual representation of the network. void dump(); /// Dump a dotty graph that depicts the module. void dumpDAG(); + + /// \returns the list of nodes that the graph owns. + const std::vector &getNodes() const { return nodes_; } + + /// \returns the list of variables that the graph owns. + const std::vector &getVars() const { return vars_; } }; } // namespace glow diff --git a/include/glow/Graph/Node.h b/include/glow/Graph/Node.h index 2cd8e73a6c..e9dae953a0 100644 --- a/include/glow/Graph/Node.h +++ b/include/glow/Graph/Node.h @@ -3,8 +3,8 @@ #include "llvm/ADT/StringRef.h" +#include "glow/Base/Type.h" #include "glow/IR/Traits.h" -#include "glow/IR/Type.h" namespace glow { diff --git a/include/glow/Graph/Nodes.h b/include/glow/Graph/Nodes.h index 8b019f52e1..d3f0149ad2 100644 --- a/include/glow/Graph/Nodes.h +++ b/include/glow/Graph/Nodes.h @@ -2,14 +2,16 @@ #define GLOW_GRAPH_NODES_H #include "glow/Graph/Node.h" -#include "glow/IR/IR.h" -#include "glow/IR/Instrs.h" namespace glow { class Variable final : public Node { public: - using InitKind = WeightVar::InitKind; + enum class InitKind { + Extern, // No initialization. + Broadcast, // Broadcast a single value to all elements. + Xavier, // Init the tensor with random values using the Xavier method. + }; private: /// The value to use during initialization. This can be the value to splat or @@ -69,18 +71,33 @@ class ConvolutionNode final : public Node { std::string getDebugDesc() const override; void visit(Node *parent, NodeVisitor *visitor) override; + + /// Calculate the size of the output tensor based on the convolution + /// parameters. + static std::pair calculateOutputDims(size_t sx, size_t sy, + size_t pad, + size_t filterSize, + size_t stride) { + size_t outsx = ((sx + pad * 2 - filterSize) / stride + 1); + size_t outsy = ((sy + pad * 2 - filterSize) / stride + 1); + return {outsx, outsy}; + } }; class PoolNode final : public Node { public: - using OpKind = PoolInst::OpKind; + /// Specifies the kind of pooling done by the operator. + enum class OpKind { + Max, + Avg, + }; private: Node *in_; size_t kernel_; size_t stride_; size_t pad_; - PoolInst::OpKind kind_; + OpKind kind_; public: PoolNode(Node *in, TypeRef outTy, llvm::StringRef name, OpKind kind, @@ -313,12 +330,16 @@ class BatchNormalizationNode final : public Node { class ArithmeticNode final : public Node { public: - using OpKind = ArithmeticInst::OpKind; + /// Specifies the kind of pooling done by the operator. + enum class OpKind { + Add, + Mul, + }; private: Node *LHS_; Node *RHS_; - ArithmeticInst::OpKind kind_; + OpKind kind_; const char *getKindStr() const; public: diff --git a/include/glow/IR/IR.h b/include/glow/IR/IR.h index 79cbf8d42d..658b4c370c 100644 --- a/include/glow/IR/IR.h +++ b/include/glow/IR/IR.h @@ -1,19 +1,21 @@ #ifndef GLOW_IR_IR_H #define GLOW_IR_IR_H +#include "glow/Base/Type.h" #include "glow/IR/Traits.h" -#include "glow/IR/Type.h" #include "glow/IR/UseDef.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include +#include #include namespace glow { class Instruction; class Module; +class Graph; enum class OperandKind : unsigned char { In, @@ -89,42 +91,46 @@ class Instruction : public Value { }; class WeightVar; +class Value; +class Node; /// A module that represents the compilation unit. class Module final { public: + using VariableMap = std::unordered_map; using InstListTy = std::list; using WeightVarListTy = std::list; private: - /// A uniqued list of types in the module. Types in this list can be compared - /// by comparing their addresses. - std::list types_{}; + /// A reference to the graph structure. + Graph &G_; + /// A list of weights. Weights are shared between all execution context. std::list weights_{}; /// A list of instruction that represent the network. InstListTy instrs_{}; - /// Give the instructions in the module a unique name. + /// Maps Variable nodes in the original graph to the weight values that + /// represent them in the lower IR. + VariableMap variableMap{}; + + /// Assign the instructions in the module a unique name. void nameInstructions(); public: /// Add an instruction to the instr stream. void pushInstr(Instruction *I) { instrs_.push_back(I); } - Module() = default; + explicit Module(Graph &G) : G_(G) {} ~Module(); - /// Return a pointer to a uniqued type \p t in the current module. - TypeRef uniqueType(const Type &T); - - /// Return a pointer to a uniqued type \p t in the current module. - TypeRef uniqueType(ElemKind elemTy, llvm::ArrayRef dims); + /// Generate IR from the graph nodes. + void generateIR(); - /// Return the void type. - TypeRef getVoidTy(); + /// \returns a reference to the original graph. + Graph &getGraph() { return G_; } /// Verify the correctness of the module. void verify() const; @@ -135,6 +141,13 @@ class Module final { /// Dump a dotty graph that depicts the module. void dumpDAG(); + /// \returns the variable map. + VariableMap &getVariableMap() { return variableMap; } + + /// \returns the weight that the variable \p v is lowered into, or null if the + /// variable is unknown. + Value *getWeightForNode(const Node *V) const; + /// \returns the list of instructions. InstListTy &getInstrs() { return instrs_; } diff --git a/include/glow/IR/IRBuilder.h b/include/glow/IR/IRBuilder.h index b7063ea73b..694289c8c0 100644 --- a/include/glow/IR/IRBuilder.h +++ b/include/glow/IR/IRBuilder.h @@ -1,9 +1,9 @@ #ifndef GLOW_IR_IRBUILDER_H #define GLOW_IR_IRBUILDER_H +#include "glow/Base/Type.h" #include "glow/IR/IR.h" #include "glow/IR/Instrs.h" -#include "glow/IR/Type.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -22,7 +22,7 @@ class IRBuilder { std::vector activeAllocs_; public: - IRBuilder(Module &M) : M_(M) {} + explicit IRBuilder(Module &M) : M_(M) {} ~IRBuilder(); diff --git a/include/glow/IR/Instrs.def b/include/glow/IR/Instrs.def index b97222d57c..7b17aefb8c 100644 --- a/include/glow/IR/Instrs.def +++ b/include/glow/IR/Instrs.def @@ -1,3 +1,12 @@ +#ifndef DEF_INSTR +#error "The macro DEF_INSTR was not declared." +#endif +#ifndef DEF_NODE +#error "The macro DEF_NODE was not declared." +#endif +#ifndef DEF_VALUE +#error "The macro DEF_VALUE was not declared." +#endif DEF_INSTR(AllocActivationInst, alloc) DEF_INSTR(DeallocActivationInst, dealloc) @@ -23,3 +32,6 @@ DEF_NODE(ReturnInst, return) // Variables (exist as memory/variable declarations): DEF_VALUE(WeightVar, weight) +#undef DEF_INSTR +#undef DEF_VALUE +#undef DEF_NODE diff --git a/include/glow/IR/Instrs.h b/include/glow/IR/Instrs.h index 751cd6149b..f85357f126 100644 --- a/include/glow/IR/Instrs.h +++ b/include/glow/IR/Instrs.h @@ -1,8 +1,9 @@ #ifndef GLOW_IR_INSTRS_H #define GLOW_IR_INSTRS_H +#include "glow/Base/Type.h" +#include "glow/Graph/Nodes.h" #include "glow/IR/IR.h" -#include "glow/IR/Type.h" #include "glow/Support/Casting.h" #include "llvm/ADT/ArrayRef.h" @@ -88,26 +89,11 @@ class ConvolutionInst : public Instruction { size_t getDepth() const { return depth_; } void verify() const; - - /// Calculate the size of the output tensor based on the convolution - /// parameters. - static std::pair calculateOutputDims(size_t sx, size_t sy, - size_t pad, - size_t filterSize, - size_t stride) { - size_t outsx = ((sx + pad * 2 - filterSize) / stride + 1); - size_t outsy = ((sy + pad * 2 - filterSize) / stride + 1); - return {outsx, outsy}; - } }; class PoolInst : public Instruction { public: - /// Specifies the kind of pooling done by the operator. - enum class OpKind { - Max, - Avg, - }; + using OpKind = PoolNode::OpKind; private: size_t kernel_; @@ -354,11 +340,7 @@ class BatchNormalizationInst : public Instruction { class ArithmeticInst : public Instruction { public: - /// Specifies the kind of pooling done by the operator. - enum class OpKind { - Add, - Mul, - }; + using OpKind = ArithmeticNode::OpKind; private: OpKind kind_; @@ -424,11 +406,7 @@ class LocalResponseNormalizationInst : public Instruction { class WeightVar : public Value { public: - enum class InitKind { - Extern, // No initialization. - Broadcast, // Broadcast a single value to all elements. - Xavier, // Init the tensor with random values using the Xavier method. - }; + using InitKind = Variable::InitKind; private: /// The value to use during initialization. This can be the value to splat or diff --git a/include/glow/IR/Traits.h b/include/glow/IR/Traits.h index 3f0ae59b7f..f28e718812 100644 --- a/include/glow/IR/Traits.h +++ b/include/glow/IR/Traits.h @@ -1,7 +1,7 @@ #ifndef GLOW_IR_TRAITS_H #define GLOW_IR_TRAITS_H -#include "glow/IR/Type.h" +#include "glow/Base/Type.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" @@ -50,9 +50,6 @@ class Kinded { #define DEF_VALUE(CLASS, NAME) CLASS##Kind, #define DEF_NODE(CLASS, NAME) CLASS##Kind, #include "glow/IR/Instrs.def" -#undef DEF_INSTR -#undef DEF_VALUE -#undef DEF_NODE }; static const char *getKindName(Kind IK) { @@ -61,9 +58,6 @@ class Kinded { #define DEF_VALUE(CLASS, NAME) #NAME, #define DEF_NODE(CLASS, NAME) #NAME, #include "glow/IR/Instrs.def" -#undef DEF_INSTR -#undef DEF_VALUE -#undef DEF_NODE nullptr}; return names[(int)IK]; } @@ -74,7 +68,7 @@ class Kinded { public: /// Ctor. - Kinded(Kind vk) : kind_(vk) {} + explicit Kinded(Kind vk) : kind_(vk) {} /// Returns the kind of the instruction. Kind getKind() const { return kind_; } diff --git a/include/glow/IR/UseDef.h b/include/glow/IR/UseDef.h index e21aeca081..af08093694 100644 --- a/include/glow/IR/UseDef.h +++ b/include/glow/IR/UseDef.h @@ -38,8 +38,9 @@ template class UseDef { /// Returns true if the user \p I is in the list. bool hasUser(const UserTy *I) const { for (const auto &U : users_) { - if (U.second == I) + if (U.second == I) { return true; + } } return false; } diff --git a/include/glow/Importer/Caffe2.h b/include/glow/Importer/Caffe2.h index 80b7c39663..8a1f3391ee 100644 --- a/include/glow/Importer/Caffe2.h +++ b/include/glow/Importer/Caffe2.h @@ -4,6 +4,7 @@ #include "llvm/ADT/ArrayRef.h" #include "glow/Graph/Graph.h" +#include "glow/Support/Casting.h" #include #include @@ -25,8 +26,7 @@ class Value; class caffe2ModelLoader { /// The interpreter that runs the program. Interpreter &IP_; - /// The graph that we are building. - Graph &G_; + /// Saves network nodes by name. std::unordered_map nodeByName_; /// A list of weight tensors indexed by name. diff --git a/include/glow/Interpreter/Interpreter.h b/include/glow/Interpreter/Interpreter.h index 26556f2b8d..4ac67d2c4d 100644 --- a/include/glow/Interpreter/Interpreter.h +++ b/include/glow/Interpreter/Interpreter.h @@ -1,11 +1,11 @@ #ifndef GLOW_INTERPRETER_INTERPRETER_H #define GLOW_INTERPRETER_INTERPRETER_H +#include "glow/Base/Tensor.h" +#include "glow/Base/Train.h" #include "glow/Graph/Graph.h" #include "glow/IR/IR.h" #include "glow/IR/IRBuilder.h" -#include "glow/Network/Tensor.h" -#include "glow/Network/Train.h" #include "glow/Optimizer/Optimizer.h" #include "llvm/ADT/ArrayRef.h" @@ -19,10 +19,10 @@ class Context; /// This is the IR-interpreter. It owns the IR, and the heap, and is able to /// execute the instructions one at a time. class Interpreter final { - /// The Module that holds the IR. - Module M_; /// The Graph that represents the high-level program. Graph G_; + /// The Module that holds the IR. + Module M_; /// Maps values to Tensors, that are owned by this class. std::unordered_map tensors_; @@ -133,8 +133,6 @@ class Interpreter final { void fwd##CLASS(Context *ctx, bool isTrain, const CLASS *I); \ void bwd##CLASS(Context *ctx, const CLASS *I); #include "glow/IR/Instrs.def" -#undef DEF_INSTR -#undef DEF_VALUE void fwdPoolMax_impl(Context *ctx, const PoolInst *I); void fwdPoolAvg_impl(Context *ctx, const PoolInst *I); diff --git a/include/glow/Support/Casting.h b/include/glow/Support/Casting.h index cc3104ec41..e1c8feb0a9 100644 --- a/include/glow/Support/Casting.h +++ b/include/glow/Support/Casting.h @@ -15,8 +15,9 @@ template TO *cast(FROM *k) { } template TO *dyn_cast(FROM *k) { - if (isa(k)) + if (isa(k)) { return cast(k); + } return nullptr; } diff --git a/src/glow/Network/CMakeLists.txt b/src/glow/Base/CMakeLists.txt similarity index 69% rename from src/glow/Network/CMakeLists.txt rename to src/glow/Base/CMakeLists.txt index 6b29ce833d..40b17d3c47 100644 --- a/src/glow/Network/CMakeLists.txt +++ b/src/glow/Base/CMakeLists.txt @@ -1,18 +1,19 @@ -add_library(Network +add_library(Base Train.cpp + Type.cpp Image.cpp) -target_link_libraries(Network +target_link_libraries(Base PUBLIC IR) if(PNG_FOUND) - target_compile_definitions(Network + target_compile_definitions(Base PRIVATE WITH_PNG=1) - target_include_directories(Network + target_include_directories(Base PRIVATE ${PNG_INCLUDE_DIR}) - target_link_libraries(Network + target_link_libraries(Base PRIVATE ${PNG_LIBRARY}) endif() diff --git a/src/glow/Network/Image.cpp b/src/glow/Base/Image.cpp similarity index 80% rename from src/glow/Network/Image.cpp rename to src/glow/Base/Image.cpp index 0a082f4bbd..4ad593ec45 100644 --- a/src/glow/Network/Image.cpp +++ b/src/glow/Base/Image.cpp @@ -1,7 +1,7 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. -#include "glow/Network/Image.h" -#include "glow/Network/Tensor.h" +#include "glow/Base/Image.h" +#include "glow/Base/Tensor.h" #include "glow/Support/Support.h" using namespace glow; @@ -15,26 +15,31 @@ bool glow::readPngImage(Tensor *T, const char *filename, // open file and test for it being a png. FILE *fp = fopen(filename, "rb"); // Can't open the file. - if (!fp) + if (!fp) { return true; + } // Validate signature. fread(header, 1, 8, fp); - if (png_sig_cmp(header, 0, 8)) + if (png_sig_cmp(header, 0, 8)) { return true; + } // Initialize stuff. png_structp png_ptr = - png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if (!png_ptr) + png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if (!png_ptr) { return true; + } png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) + if (!info_ptr) { return true; + } - if (setjmp(png_jmpbuf(png_ptr))) + if (setjmp(png_jmpbuf(png_ptr))) { return true; + } png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); @@ -58,12 +63,14 @@ bool glow::readPngImage(Tensor *T, const char *filename, png_read_update_info(png_ptr, info_ptr); // Error during image read. - if (setjmp(png_jmpbuf(png_ptr))) + if (setjmp(png_jmpbuf(png_ptr))) { return true; + } - png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height); - for (size_t y = 0; y < height; y++) + auto *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height); + for (size_t y = 0; y < height; y++) { row_pointers[y] = (png_byte *)malloc(png_get_rowbytes(png_ptr, info_ptr)); + } png_read_image(png_ptr, row_pointers); fclose(fp); @@ -85,8 +92,9 @@ bool glow::readPngImage(Tensor *T, const char *filename, } } - for (size_t y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { free(row_pointers[y]); + } free(row_pointers); return false; @@ -96,27 +104,32 @@ bool glow::writePngImage(Tensor *T, const char *filename, std::pair range) { /* create file */ FILE *fp = fopen(filename, "wb"); - if (!fp) + if (!fp) { return true; + } /* initialize stuff */ png_structp png_ptr = - png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if (!png_ptr) + if (!png_ptr) { return true; + } png_infop info_ptr = png_create_info_struct(png_ptr); - if (!info_ptr) + if (!info_ptr) { return true; + } - if (setjmp(png_jmpbuf(png_ptr))) + if (setjmp(png_jmpbuf(png_ptr))) { return true; + } png_init_io(png_ptr, fp); - if (setjmp(png_jmpbuf(png_ptr))) + if (setjmp(png_jmpbuf(png_ptr))) { return true; + } auto H = T->getHandle(); @@ -134,12 +147,14 @@ bool glow::writePngImage(Tensor *T, const char *filename, png_write_info(png_ptr, info_ptr); - if (setjmp(png_jmpbuf(png_ptr))) + if (setjmp(png_jmpbuf(png_ptr))) { return true; + } - png_bytep *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height); - for (size_t y = 0; y < height; y++) + auto *row_pointers = (png_bytep *)malloc(sizeof(png_bytep) * height); + for (size_t y = 0; y < height; y++) { row_pointers[y] = (png_byte *)malloc(png_get_rowbytes(png_ptr, info_ptr)); + } float scale = ((range.second - range.first) / 255.0); float bias = range.first; @@ -157,14 +172,16 @@ bool glow::writePngImage(Tensor *T, const char *filename, png_write_image(png_ptr, row_pointers); - if (setjmp(png_jmpbuf(png_ptr))) + if (setjmp(png_jmpbuf(png_ptr))) { return true; + } - png_write_end(png_ptr, NULL); + png_write_end(png_ptr, nullptr); /* cleanup heap allocation */ - for (size_t y = 0; y < height; y++) + for (size_t y = 0; y < height; y++) { free(row_pointers[y]); + } free(row_pointers); fclose(fp); return false; diff --git a/src/glow/Network/Train.cpp b/src/glow/Base/Train.cpp similarity index 96% rename from src/glow/Network/Train.cpp rename to src/glow/Base/Train.cpp index 5ab76954ba..f46cc8e267 100644 --- a/src/glow/Network/Train.cpp +++ b/src/glow/Base/Train.cpp @@ -1,7 +1,7 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. -#include "glow/Network/Train.h" -#include "glow/Network/Tensor.h" +#include "glow/Base/Train.h" +#include "glow/Base/Tensor.h" using namespace glow; diff --git a/src/glow/IR/Type.cpp b/src/glow/Base/Type.cpp similarity index 94% rename from src/glow/IR/Type.cpp rename to src/glow/Base/Type.cpp index 144914f3b1..e68d4f67a5 100644 --- a/src/glow/IR/Type.cpp +++ b/src/glow/Base/Type.cpp @@ -1,6 +1,6 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. -#include "glow/IR/Type.h" +#include "glow/Base/Type.h" #include diff --git a/src/glow/CMakeLists.txt b/src/glow/CMakeLists.txt index 88dead0a66..0f8ef6f3ee 100644 --- a/src/glow/CMakeLists.txt +++ b/src/glow/CMakeLists.txt @@ -1,10 +1,9 @@ +add_subdirectory(Base) add_subdirectory(Graph) add_subdirectory(IR) add_subdirectory(Importer) add_subdirectory(Interpreter) -add_subdirectory(Models) -add_subdirectory(Network) add_subdirectory(Optimizer) add_subdirectory(Support) diff --git a/src/glow/Graph/CMakeLists.txt b/src/glow/Graph/CMakeLists.txt index 3309333ba6..12351f26b0 100644 --- a/src/glow/Graph/CMakeLists.txt +++ b/src/glow/Graph/CMakeLists.txt @@ -1,10 +1,9 @@ add_library(Graph - IRGen.cpp Nodes.cpp Graph.cpp) target_link_libraries(Graph PUBLIC - IR + Base Support) diff --git a/src/glow/Graph/Graph.cpp b/src/glow/Graph/Graph.cpp index ccaa439eba..df0bbfd429 100644 --- a/src/glow/Graph/Graph.cpp +++ b/src/glow/Graph/Graph.cpp @@ -20,6 +20,22 @@ Graph::~Graph() { } } +TypeRef Graph::uniqueType(ElemKind elemTy, llvm::ArrayRef dims) { + return uniqueType(Type(elemTy, dims)); +} + +TypeRef Graph::uniqueType(const Type &T) { + for (auto &tp : types_) { + if (T.isEqual(tp)) { + return &tp; + } + } + + return &*types_.insert(types_.begin(), T); +} + +TypeRef Graph::getVoidTy() { return uniqueType(Type()); } + //===----------------------------------------------------------------------===// // Node builders //===----------------------------------------------------------------------===// @@ -32,7 +48,7 @@ Variable *Graph::createVariable(TypeRef T, llvm::StringRef name, Variable *Graph::createVariable(ElemKind T, llvm::ArrayRef dims, llvm::StringRef name, Variable::InitKind initKind, float val) { - auto FT = M_.uniqueType(T, dims); + auto FT = uniqueType(T, dims); return createVariable(FT, name, initKind, val); } @@ -45,7 +61,7 @@ ConvolutionNode *Graph::createConv(llvm::StringRef name, Node *input, // Calculate the size and allocate the output buffer. auto outSz = - ConvolutionInst::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); + ConvolutionNode::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); std::vector outDims = {idim.n, outSz.first, outSz.second, depth}; @@ -58,7 +74,7 @@ ConvolutionNode *Graph::createConv(llvm::StringRef name, Node *input, auto *bias = createVariable(ElemKind::FloatTy, {depth}, "bias", Variable::InitKind::Broadcast, 0.1); - auto OT = M_.uniqueType(ElemKind::FloatTy, outDims); + auto OT = uniqueType(ElemKind::FloatTy, outDims); return addNode(new ConvolutionNode(input, OT, name, filter, bias, kernel, stride, pad, depth)); @@ -72,10 +88,10 @@ PoolNode *Graph::createPool(llvm::StringRef name, Node *input, "buffer too small for selected stride"); auto outSz = - ConvolutionInst::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); + ConvolutionNode::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); - auto OT = M_.uniqueType(ElemKind::FloatTy, - {idim.n, outSz.first, outSz.second, idim.c}); + auto OT = uniqueType(ElemKind::FloatTy, + {idim.n, outSz.first, outSz.second, idim.c}); return addNode(new PoolNode(input, OT, name, kind, kernel, stride, pad)); } @@ -93,7 +109,7 @@ FullyConnectedNode *Graph::createFullyConnected(llvm::StringRef name, auto *B = createVariable(T->getElementType(), {outDepth}, "bias", Variable::InitKind::Broadcast, 0.1); - auto OT = M_.uniqueType(T->getElementType(), {idim.first, outDepth}); + auto OT = uniqueType(T->getElementType(), {idim.first, outDepth}); return addNode(new FullyConnectedNode(input, OT, name, W, B, outDepth)); } @@ -132,7 +148,7 @@ TransposeNode *Graph::createTranspose(llvm::StringRef name, Node *input, shape.push_back(dims[shuffle[i]]); } - auto NT = M_.uniqueType(input->getElementType(), shape); + auto NT = uniqueType(input->getElementType(), shape); return addNode(new TransposeNode(input, NT, name, shuffle)); } @@ -151,7 +167,7 @@ ConcatNode *Graph::createConcat(llvm::StringRef name, // increase the size of the tensor along this dimension. shape[dimension] *= inputs.size(); - auto NT = M_.uniqueType(inputs[0]->getElementType(), shape); + auto NT = uniqueType(inputs[0]->getElementType(), shape); return addNode(new ConcatNode(inputs, NT, name, dimension)); } @@ -191,7 +207,7 @@ Graph::createLocalResponseNormalization(llvm::StringRef name, Node *input, } ArithmeticNode *Graph::createArithmetic(llvm::StringRef name, Node *LHS, - Node *RHS, ArithmeticInst::OpKind op) { + Node *RHS, ArithmeticNode::OpKind op) { assert(LHS->dims() == RHS->dims() && "Invalid operand shapes"); // The output tensor is of the same shape as the input tensor. return addNode(new ArithmeticNode(name, LHS, RHS, op)); @@ -202,7 +218,7 @@ ReturnNode *Graph::createReturn(llvm::StringRef name, Node *input) { } //===----------------------------------------------------------------------===// -// Graph Utilities +// Graph dumping and printing //===----------------------------------------------------------------------===// void Graph::dump() { @@ -230,7 +246,9 @@ struct DottyPrinterPass : NodeVisitor { DottyPrinterPass() = default; - void pre(Node *parent, Node *N) override { nodeEdges.push_back({parent, N}); } + void pre(Node *parent, Node *N) override { + nodeEdges.emplace_back(parent, N); + } std::string nodeDescr(Node *N) { if (!N) { diff --git a/src/glow/Graph/Nodes.cpp b/src/glow/Graph/Nodes.cpp index ede88ad63f..1cdc2a60f8 100644 --- a/src/glow/Graph/Nodes.cpp +++ b/src/glow/Graph/Nodes.cpp @@ -1,8 +1,8 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. #include "glow/Graph/Nodes.h" +#include "glow/Base/Type.h" #include "glow/IR/Instrs.h" -#include "glow/IR/Type.h" #include "glow/Support/Support.h" using namespace glow; diff --git a/src/glow/IR/CMakeLists.txt b/src/glow/IR/CMakeLists.txt index 52be444171..81b5fc1e0c 100644 --- a/src/glow/IR/CMakeLists.txt +++ b/src/glow/IR/CMakeLists.txt @@ -1,10 +1,11 @@ add_library(IR IR.cpp - Type.cpp + IRGen.cpp IRBuilder.cpp Instrs.cpp) target_link_libraries(IR PUBLIC + Base Support) diff --git a/src/glow/IR/IR.cpp b/src/glow/IR/IR.cpp index 32488a093d..39fad6ade6 100644 --- a/src/glow/IR/IR.cpp +++ b/src/glow/IR/IR.cpp @@ -12,31 +12,21 @@ using namespace glow; -TypeRef Module::uniqueType(ElemKind elemTy, llvm::ArrayRef dims) { - return uniqueType(Type(elemTy, dims)); -} - -TypeRef Module::uniqueType(const Type &T) { - for (auto &tp : types_) { - if (T.isEqual(tp)) - return &tp; - } - - return &*types_.insert(types_.begin(), T); -} - -TypeRef Module::getVoidTy() { return uniqueType(Type()); } +//===----------------------------------------------------------------------===// +// General IR operations +//===----------------------------------------------------------------------===// void Instruction::pushOperand(Operand op) { - ops_.push_back({nullptr, op.second}); + ops_.emplace_back(nullptr, op.second); setOperand(ops_.size() - 1, op.first); } void Instruction::setOperand(unsigned idx, Value *v) { auto *currVal = ops_[idx].first; - if (currVal == v) + if (currVal == v) { return; + } if (currVal) { currVal->removeUse({idx, this}); @@ -54,8 +44,8 @@ Instruction::Operand Instruction::getOperand(unsigned idx) const { } void Instruction::verifyUseList() const { - for (size_t i = 0, e = ops_.size(); i < e; i++) { - auto *v = ops_[i].first; + for (const auto &op : ops_) { + auto *v = op.first; (void)v; assert(v && "Instruction operand must be a real value"); assert(v->hasUser(this) && "Invalid use-list"); @@ -69,9 +59,6 @@ void Instruction::verify() const { #define DEF_VALUE(CLASS, NAME) #define DEF_NODE(CLASS, NAME) #include "glow/IR/Instrs.def" -#undef DEF_INSTR -#undef DEF_VALUE -#undef DEF_NODE } Module::~Module() { @@ -88,13 +75,26 @@ Module::~Module() { } void Module::verify() const { - assert(instrs_.size() && "Instruction list is empty!"); + assert(!instrs_.empty() && "Instruction list is empty!"); for (auto it : instrs_) { it->verifyUseList(); it->verify(); } } +Value *Module::getWeightForNode(const Node *V) const { + auto it = variableMap.find(V); + if (it == variableMap.end()) { + return nullptr; + } + + return it->second; +} + +//===----------------------------------------------------------------------===// +// IR printing and visualizing +//===----------------------------------------------------------------------===// + static std::string getExtraDesc(const Kinded *K) { #define DEF_NODE(CLASS, NAME) #define DEF_INSTR(CLASS, NAME) \ @@ -105,9 +105,6 @@ static std::string getExtraDesc(const Kinded *K) { return X->getExtraDesc(); #include "glow/IR/Instrs.def" -#undef DEF_INSTR -#undef DEF_VALUE -#undef DEF_NODE glow_unreachable(); } @@ -118,9 +115,6 @@ bool Instruction::mayShareBuffers(const Instruction *I) { #define DEF_VALUE(CLASS, NAME) #define DEF_NODE(CLASS, NAME) #include "glow/IR/Instrs.def" -#undef DEF_INSTR -#undef DEF_VALUE -#undef DEF_NODE glow_unreachable(); } @@ -140,7 +134,7 @@ static std::string getDesc(const Instruction *II) { sb += "%" + name + " = " + instrName + " "; auto extraDesc = getExtraDesc(II); ; - if (extraDesc.size()) { + if (!extraDesc.empty()) { sb += extraDesc + " "; } @@ -162,9 +156,10 @@ static void nameInstr(std::unordered_set &usedNames, Named *named, llvm::StringRef suggestion) { unsigned idx = 0; - if (!named->hasName()) - // Use the first few letters of the value as the initial name. + // Use the first few letters of the value as the initial name. + if (!named->hasName()) { named->setName(suggestion.slice(0, 4)); + } std::string tempName = named->getName(); @@ -224,7 +219,7 @@ static std::string getDottyDesc(const Instruction *II) { sb += instrName; sb += "|"; auto extraDesc = getExtraDesc(II); - if (extraDesc.size()) { + if (!extraDesc.empty()) { sb += extraDesc + "|"; } diff --git a/src/glow/IR/IRBuilder.cpp b/src/glow/IR/IRBuilder.cpp index af0b7e4f04..487a9020ae 100644 --- a/src/glow/IR/IRBuilder.cpp +++ b/src/glow/IR/IRBuilder.cpp @@ -1,5 +1,7 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. +#include "glow/Graph/Graph.h" + #include "glow/IR/IRBuilder.h" using namespace glow; @@ -46,7 +48,7 @@ ConvolutionInst *IRBuilder::createConvOp(Value *input, Value *filter, // Calculate the size and allocate the output buffer. auto outSz = - ConvolutionInst::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); + ConvolutionNode::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); std::vector outDims = {idim.n, outSz.first, outSz.second, depth}; @@ -63,7 +65,7 @@ PoolInst *IRBuilder::createPoolOp(Value *input, PoolInst::OpKind kind, "buffer too small for selected stride"); auto outSz = - ConvolutionInst::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); + ConvolutionNode::calculateOutputDims(idim.h, idim.w, pad, kernel, stride); // Allocate cache arrays that store the x and y coordinates of the incoming // gradient for each max element. @@ -353,7 +355,7 @@ WeightVar *IRBuilder::createWeightVar(ElemKind elemTy, llvm::ArrayRef dims, llvm::StringRef name, InitKind initKind, float val) { - auto T = M_.uniqueType(elemTy, dims); + auto T = M_.getGraph().uniqueType(elemTy, dims); return createWeightVar(T, name, initKind, val); } @@ -375,7 +377,7 @@ IRBuilder::createAllocActivationInst(TypeRef T, llvm::StringRef name) { } AllocActivationInst *IRBuilder::createAllocActivationInst( ElemKind elemTy, llvm::ArrayRef dims, llvm::StringRef name) { - auto T = M_.uniqueType(elemTy, dims); + auto T = M_.getGraph().uniqueType(elemTy, dims); return createAllocActivationInst(T, name); } diff --git a/src/glow/Graph/IRGen.cpp b/src/glow/IR/IRGen.cpp similarity index 89% rename from src/glow/Graph/IRGen.cpp rename to src/glow/IR/IRGen.cpp index a4b4301771..4b0be7e374 100644 --- a/src/glow/Graph/IRGen.cpp +++ b/src/glow/IR/IRGen.cpp @@ -2,6 +2,7 @@ #include "glow/Graph/Graph.h" #include "glow/Graph/Nodes.h" +#include "glow/IR/IR.h" #include "glow/IR/IRBuilder.h" #include "glow/Support/Casting.h" @@ -17,8 +18,10 @@ namespace { /// A helper class for visiting and generating the dotty file from the graph. struct IRGenVisitor : NodeVisitor { + using NodeToInstrTy = std::unordered_map; + /// Holds the mapping between graph nodes to IR variables. - Graph::NodeToInstrTy generatedNodes; + NodeToInstrTy generatedNodes; /// The module that we are building. Module &M_; /// The builder that adds instructions into the module. @@ -30,7 +33,7 @@ struct IRGenVisitor : NodeVisitor { return !generatedNodes.count(N); } - IRGenVisitor(Module &M) : M_(M), builder_(M_) {} + explicit IRGenVisitor(Module &M) : M_(M), builder_(M_) {} /// \returns the generated instruction for the node \p N. Value *valueForNode(Node *N) { @@ -41,9 +44,12 @@ struct IRGenVisitor : NodeVisitor { /// Saves the generated IR in \p v for the node \p N. void registerIR(Node *N, Value *v) { assert(!generatedNodes.count(N) && "Already generated code for this node"); - assert(isa(v) || - isa(v) && "Value operand must be a memory location"); + assert((isa(v) || isa(v)) && + "Value operand must be a memory location"); generatedNodes[N] = v; + // Register the fact that we've lowered this variable to the new weight. + auto &map = M_.getVariableMap(); + map[N] = v; } void post(Node *parent, Node *N) override { @@ -205,38 +211,17 @@ struct IRGenVisitor : NodeVisitor { } } } - - /// \returns the mapping between the graph nodes to the IR instructions. - Graph::NodeToInstrTy &getMapping() { return generatedNodes; } }; } // namespace -void Graph::registerIRMap(const Node *N, Value *V) { - assert(!IRMap.count(N) && "Node already in map"); - IRMap[N] = V; -} +void Module::generateIR() { + IRGenVisitor irgen(*this); -Value *Graph::getIRForNode(const Node *N) const { - auto it = IRMap.find(N); - if (it == IRMap.end()) { - return nullptr; - } - return it->second; -} - -void Graph::generateIR() { - IRGenVisitor irgen(M_); - - for (auto &N : vars_) { + for (auto &N : G_.getVars()) { N->visit(nullptr, &irgen); } - for (auto &N : nodes_) { + for (auto &N : G_.getNodes()) { N->visit(nullptr, &irgen); } - - // Record the lowering of the nodes in the Graph class. - for (auto p : irgen.getMapping()) { - registerIRMap(p.first, p.second); - } } diff --git a/src/glow/IR/Instrs.cpp b/src/glow/IR/Instrs.cpp index 7e03797c92..6601e1f105 100644 --- a/src/glow/IR/Instrs.cpp +++ b/src/glow/IR/Instrs.cpp @@ -35,6 +35,10 @@ template std::string arrayRefToString(llvm::ArrayRef list) { } } // namespace +//===----------------------------------------------------------------------===// +// Instruction textual printers +//===----------------------------------------------------------------------===// + std::string ConvolutionInst::getExtraDesc() const { return listToString(kernel_, stride_, pad_, depth_); } @@ -105,6 +109,10 @@ std::string AllocActivationInst::getExtraDesc() const { return std::to_string(*getType()); } +//===----------------------------------------------------------------------===// +// Instruction verification +//===----------------------------------------------------------------------===// + /// Check that the type of the first operand matches the type of the second /// operand. static void checkSameType(Instruction::Operand A, Instruction::Operand B) { @@ -135,7 +143,7 @@ void ConvolutionInst::verify() const { assert(idim.w >= kernel_ && idim.h >= kernel_ && "buffer too small for selected stride"); - auto outSz = ConvolutionInst::calculateOutputDims(idim.h, idim.w, pad_, + auto outSz = ConvolutionNode::calculateOutputDims(idim.h, idim.w, pad_, kernel_, stride_); ShapeNHWC exp(idim.n, outSz.first, outSz.second, depth_); (void)exp; @@ -159,7 +167,7 @@ void PoolInst::verify() const { assert(idim.w >= kernel_ && idim.h >= kernel_ && "buffer too small for selected stride"); - auto outSz = ConvolutionInst::calculateOutputDims(idim.h, idim.w, pad_, + auto outSz = ConvolutionNode::calculateOutputDims(idim.h, idim.w, pad_, kernel_, stride_); ShapeNHWC exp(idim.n, outSz.first, outSz.second, idim.c); (void)exp; diff --git a/src/glow/Importer/Caffe2.cpp b/src/glow/Importer/Caffe2.cpp index dee6627c8d..61c79b9c2b 100644 --- a/src/glow/Importer/Caffe2.cpp +++ b/src/glow/Importer/Caffe2.cpp @@ -1,13 +1,14 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. #include "glow/Importer/Caffe2.h" +#include "glow/Base/Tensor.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/Network/Tensor.h" +#include "glow/Support/Casting.h" #include "caffe.pb.h" #include @@ -109,19 +110,22 @@ Node *caffe2ModelLoader::getNodeByName(const std::string &name) { } Node *caffe2ModelLoader::getOrCreateNodeByName(const std::string &name) { + auto &G = IP_.getGraph(); auto it = nodeByName_.find(name); if (it != nodeByName_.end()) { return it->second; } Tensor *T = getTensorByName(name); - auto *V = G_.createVariable(T->getElementType(), T->dims(), name, - Variable::InitKind::Broadcast); + auto *V = G.createVariable(T->getElementType(), T->dims(), name, + Variable::InitKind::Broadcast); nodeByName_[name] = V; return V; } void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { + auto &G = IP_.getGraph(); + ArgumentDictionaryTy dict = loadArgumenrMap(op); const std::string &typeName = op.type(); @@ -130,7 +134,7 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { // Load the inputs: auto *in = getOrCreateNodeByName(op.input(0)); // Create the RELU: - auto *R = G_.createRELU(op.name(), in); + auto *R = G.createRELU(op.name(), in); // Save the outputs: for (int i = 0, e = op.output_size(); i < e; i++) { nodeByName_[op.output(i)] = R; @@ -181,14 +185,14 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { tensors_[op.name() + "_conv_bias"] = b; } - auto *tr = G_.createTranspose(op.name(), in, NCHW2NHWC); - auto *node = G_.createConv(op.name(), tr, numFilters, kernel, stride, pad); + auto *tr = G.createTranspose(op.name(), in, NCHW2NHWC); + auto *node = G.createConv(op.name(), tr, numFilters, kernel, stride, pad); // Load the weights into the operator. registerVariableInit(node->getFilter(), wtag); registerVariableInit(node->getBias(), b); - auto *N = G_.createTranspose(op.name(), node, NHWC2NCHW); + auto *N = G.createTranspose(op.name(), node, NHWC2NCHW); // Save the outputs: for (int i = 0, e = op.output_size(); i < e; i++) { nodeByName_[op.output(i)] = N; @@ -206,9 +210,9 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { int pad = dict.count("pad") ? loadInt(dict["pad"]) : 0; int kernel = loadInt(dict["kernel"]); - auto *tr = G_.createTranspose(op.name(), in, NCHW2NHWC); - auto *node = G_.createPool(op.name(), tr, opk, kernel, stride, pad); - auto *N = G_.createTranspose(op.name(), node, NHWC2NCHW); + auto *tr = G.createTranspose(op.name(), in, NCHW2NHWC); + auto *node = G.createPool(op.name(), tr, opk, kernel, stride, pad); + auto *N = G.createTranspose(op.name(), node, NHWC2NCHW); // Save the outputs: for (int i = 0, e = op.output_size(); i < e; i++) { @@ -244,7 +248,7 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { assert(false && "Invalid order field"); } - auto *node = G_.createBatchNormalization(op.name(), in, channel, epsilon); + auto *node = G.createBatchNormalization(op.name(), in, channel, epsilon); // Load the weights. registerVariableInit(node->getScale(), scale); @@ -261,7 +265,7 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { auto *in0 = getOrCreateNodeByName(op.input(0)); auto *in1 = getOrCreateNodeByName(op.input(1)); auto *node = - G_.createArithmetic(op.name(), in0, in1, ArithmeticInst::OpKind::Add); + G.createArithmetic(op.name(), in0, in1, ArithmeticNode::OpKind::Add); // Save the outputs: for (int i = 0, e = op.output_size(); i < e; i++) { nodeByName_[op.output(i)] = node; @@ -275,7 +279,7 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { // Load the inputs: auto *in = getOrCreateNodeByName(op.input(0)); - auto *node = G_.createSoftMax(op.name(), in, softmaxExpected); + auto *node = G.createSoftMax(op.name(), in, softmaxExpected); // Save the outputs: for (int i = 0, e = op.output_size(); i < e; i++) { nodeByName_[op.output(i)] = node; @@ -287,7 +291,7 @@ void caffe2ModelLoader::loadOperator(const caffe2::OperatorDef &op) { auto *in = getOrCreateNodeByName(op.input(0)); Tensor *w = getTensorByName(op.input(1)); Tensor *b = getTensorByName(op.input(2)); - auto *FC = G_.createFullyConnected(op.name(), in, b->size()); + auto *FC = G.createFullyConnected(op.name(), in, b->size()); // Load weights. registerVariableInit(FC->getFilter(), w); @@ -391,7 +395,7 @@ caffe2ModelLoader::caffe2ModelLoader(const std::string &netDescFilename, llvm::ArrayRef names, llvm::ArrayRef tensors, Interpreter &IP) - : IP_(IP), G_(IP_.getGraph()) { + : IP_(IP) { // Verify that the version of the library that we linked against is // compatible with the version of the headers we compiled against. GOOGLE_PROTOBUF_VERIFY_VERSION; @@ -413,14 +417,16 @@ caffe2ModelLoader::caffe2ModelLoader(const std::string &netDescFilename, loadNetwork(networkDef); // Save the result of the last operator into a weight. - root_ = G_.createReturn("ret", root_); + auto &G = IP_.getGraph(); + auto &M = IP_.getModule(); + root_ = G.createReturn("ret", root_); // Emit IR for the graph. - G_.generateIR(); + IP_.getModule().generateIR(); // Load the value of the variables. for (auto p : variableInit_) { - WeightVar *N = cast(G_.getIRForNode(p.first)); + WeightVar *N = cast(M.getWeightForNode(p.first)); N->setInitKind(WeightVar::InitKind::Extern); IP.initValue(N, p.second); } diff --git a/src/glow/Interpreter/CMakeLists.txt b/src/glow/Interpreter/CMakeLists.txt index 33841491ba..9fb432384c 100644 --- a/src/glow/Interpreter/CMakeLists.txt +++ b/src/glow/Interpreter/CMakeLists.txt @@ -5,6 +5,6 @@ add_library(Interpreter target_link_libraries(Interpreter PRIVATE Optimizer - Network + Base Graph) diff --git a/src/glow/Interpreter/Interpreter.cpp b/src/glow/Interpreter/Interpreter.cpp index 5e629db56b..99aacb799a 100644 --- a/src/glow/Interpreter/Interpreter.cpp +++ b/src/glow/Interpreter/Interpreter.cpp @@ -9,7 +9,7 @@ using namespace glow; -Interpreter::Interpreter() : G_(M_) {} +Interpreter::Interpreter() : M_(G_) {} Interpreter::~Interpreter() { // Delete the tensors that are owned by this module. @@ -47,7 +47,7 @@ Tensor *Interpreter::getTensorForValue(const Value *v) const { } Tensor *Interpreter::getTensorForNode(const Node *v) const { - auto val = G_.getIRForNode(v); + auto val = M_.getWeightForNode(v); assert(val && "Node does not have a registered IR value"); return getTensorForValue(val); } @@ -108,7 +108,7 @@ Handle Interpreter::getWeightHandle(Context *ctx, Value *v) const { } Handle Interpreter::getWeightHandle(Context *ctx, Variable *v) const { - auto *N = G_.getIRForNode(v); + auto *N = M_.getWeightForNode(v); return getTensorForValue(N)->getHandle(); } @@ -117,7 +117,7 @@ Handle Interpreter::getGradHandle(Context *ctx, Value *v) { } Handle Interpreter::getGradHandle(Context *ctx, Variable *v) { - auto *N = G_.getIRForNode(v); + auto *N = M_.getWeightForNode(v); return getOrCreateGradTensor(N)->getHandle(); } @@ -212,7 +212,7 @@ void Interpreter::infer(llvm::ArrayRef vars, // Update the input variables. for (int i = 0, e = vars.size(); i < e; i++) { - auto *val = G_.getIRForNode(vars[i]); + auto *val = M_.getWeightForNode(vars[i]); loadValueFromTensor(val, inputs[i], 0); } @@ -229,7 +229,7 @@ void Interpreter::train(size_t iterations, llvm::ArrayRef vars, std::vector weights; for (auto *v : vars) { - weights.push_back(G_.getIRForNode(v)); + weights.push_back(M_.getWeightForNode(v)); } // This is the size of one batch (the number of samples in the batch). @@ -277,7 +277,6 @@ void Interpreter::updateForwardBackward(llvm::ArrayRef vars, } void Interpreter::doForwardPass(bool isTrain) { - // Do the forward pass. #define DEF_VALUE(CLASS, NAME) #define DEF_NODE(CLASS, NAME) @@ -294,9 +293,6 @@ void Interpreter::doForwardPass(bool isTrain) { glow_unreachable(); } } -#undef DEF_INSTR -#undef DEF_VALUE -#undef DEF_NODE } void Interpreter::doBackwardPass() { @@ -318,7 +314,4 @@ void Interpreter::doBackwardPass() { glow_unreachable(); } } -#undef DEF_INSTR -#undef DEF_NODE -#undef DEF_VALUE } diff --git a/src/glow/Models/Builders.cpp b/src/glow/Models/Builders.cpp deleted file mode 100644 index 18897da5ff..0000000000 --- a/src/glow/Models/Builders.cpp +++ /dev/null @@ -1 +0,0 @@ -// Copyright 2017 Facebook Inc. All Rights Reserved. diff --git a/src/glow/Models/CMakeLists.txt b/src/glow/Models/CMakeLists.txt deleted file mode 100644 index fe7ed489ee..0000000000 --- a/src/glow/Models/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ - -add_library(Models - Builders.cpp) -target_link_libraries(Models - PRIVATE - Network) - diff --git a/tests/unittests/GraphTest.cpp b/tests/unittests/GraphTest.cpp index 7ed80f367a..b825af9ceb 100644 --- a/tests/unittests/GraphTest.cpp +++ b/tests/unittests/GraphTest.cpp @@ -3,6 +3,7 @@ #include "glow/Graph/Graph.h" #include "glow/Graph/Node.h" #include "glow/Graph/Nodes.h" +#include "glow/IR/IR.h" #include "gtest/gtest.h" @@ -18,8 +19,8 @@ using namespace glow; TEST(Graph, simpleTest) { { - Module M; - Graph G(M); + Graph G; + Module M(G); Node *K = G.createVariable(ElemKind::FloatTy, {4, 320, 200, 3}, "input"); Node *S = G.createVariable(ElemKind::IndexTy, {4, 1}, "select"); @@ -28,14 +29,15 @@ TEST(Graph, simpleTest) { K = G.createSoftMax("SoftMax", K, S); G.dump(); G.dumpDAG(); - G.generateIR(); + M.generateIR(); M.dump(); } { unsigned numInputs = 10; - Module M; - Graph G(M); + Graph G; + Module M(G); + auto *A = G.createVariable(ElemKind::FloatTy, {numInputs, 2}, "A"); auto *Ex = G.createVariable(ElemKind::FloatTy, {numInputs, 1}, "Ex"); @@ -46,7 +48,7 @@ TEST(Graph, simpleTest) { G.createRegression("Regression", O, Ex); G.dump(); G.dumpDAG(); - G.generateIR(); + M.generateIR(); M.dump(); } } diff --git a/tests/unittests/IRGradCheck.cpp b/tests/unittests/IRGradCheck.cpp index 4f7fa0fe6a..3c6f026841 100644 --- a/tests/unittests/IRGradCheck.cpp +++ b/tests/unittests/IRGradCheck.cpp @@ -1,12 +1,12 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. +#include "glow/Base/Tensor.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/Network/Tensor.h" #include "gtest/gtest.h" @@ -101,7 +101,7 @@ TEST(Network, gradientCheck_FC_Concat_RELU) { O = G.createRegression("reg", O, Exp); auto *result = G.createReturn("ret", O); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -138,7 +138,7 @@ TEST(Network, gradientCheck_Conv) { O = G.createRegression("reg", O, Ex); auto *result = G.createReturn("ret", O); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -173,7 +173,7 @@ TEST(Network, gradientCheck_AvgPool) { O = G.createRegression("reg", O, Exp); auto *result = G.createReturn("ret", O); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -208,7 +208,7 @@ TEST(Network, gradientCheck_batchNorm) { O = G.createRegression("reg", O, Ex); auto result = G.createReturn("ret", O); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -251,7 +251,7 @@ TEST(Network, gradientCheck_Arithmetic) { O = G.createRegression("reg", O, Exp); auto *result = G.createReturn("ret", O); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -337,7 +337,7 @@ TEST(Network, gradientCheck_FC_Concat_Tanh) { FA = G.createRegression("reg", FA, Exp); auto *result = G.createReturn("ret", FA); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -370,7 +370,7 @@ TEST(Network, gradientCheck_Transpose) { TA = G.createRegression("regress", TA, Exp); auto *result = G.createReturn("ret", TA); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); diff --git a/tests/unittests/IRTest.cpp b/tests/unittests/IRTest.cpp index a0901471fa..df60dc9553 100644 --- a/tests/unittests/IRTest.cpp +++ b/tests/unittests/IRTest.cpp @@ -1,5 +1,7 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. +#include "glow/Graph/Graph.h" + #include "glow/IR/IR.h" #include "glow/IR/IRBuilder.h" #include "glow/IR/Instrs.h" @@ -18,25 +20,27 @@ using namespace glow; TEST(IR, uniqueTypes) { - Module M; + Graph G; + Module M(G); Type T1(ElemKind::FloatTy, {320, 200}); Type T2(ElemKind::FloatTy, {320, 200}); Type T3(ElemKind::FloatTy, {1, 2}); - auto *u1 = M.uniqueType(T1); - auto *u2 = M.uniqueType(T2); - auto *u3 = M.uniqueType(T3); + auto *u1 = G.uniqueType(T1); + auto *u2 = G.uniqueType(T2); + auto *u3 = G.uniqueType(T3); EXPECT_EQ(u1, u2); EXPECT_NE(u1, u3); for (int i = 0; i < 10; i++) { - EXPECT_EQ(u1, M.uniqueType(T1)); + EXPECT_EQ(u1, G.uniqueType(T1)); } } TEST(IR, basicUseList) { - Module M; + Graph G; + Module M(G); { IRBuilder builder(M); @@ -61,11 +65,12 @@ TEST(IR, basicUseList) { TEST(IR, allInstrs) { using InitKind = WeightVar::InitKind; - Module M; - auto T1 = M.uniqueType(ElemKind::FloatTy, {1, 24, 24, 3}); - auto T2 = M.uniqueType(ElemKind::FloatTy, {64}); - auto T4 = M.uniqueType(ElemKind::IndexTy, {1, 1}); - auto T5 = M.uniqueType(ElemKind::FloatTy, {3}); + Graph G; + Module M(G); + auto T1 = G.uniqueType(ElemKind::FloatTy, {1, 24, 24, 3}); + auto T2 = G.uniqueType(ElemKind::FloatTy, {64}); + auto T4 = G.uniqueType(ElemKind::IndexTy, {1, 1}); + auto T5 = G.uniqueType(ElemKind::FloatTy, {3}); { IRBuilder builder(M); @@ -114,7 +119,8 @@ TEST(IR, allInstrs) { } TEST(IR, highLevelBuilder) { - Module M; + Graph G; + Module M(G); { IRBuilder bb(M); @@ -147,7 +153,8 @@ TEST(IR, highLevelBuilder) { } TEST(IR, casting) { - Module M; + Graph G; + Module M(G); { IRBuilder bb(M); diff --git a/tests/unittests/InterpreterTest.cpp b/tests/unittests/InterpreterTest.cpp index fb991a9ffd..75485183b9 100644 --- a/tests/unittests/InterpreterTest.cpp +++ b/tests/unittests/InterpreterTest.cpp @@ -41,7 +41,7 @@ TEST(Interpreter, interpret) { auto *SM = G.createSoftMax("sm", RL3, ex); G.createReturn("ret", SM); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Infer); IP.initVars(); IP.infer({input}, {&inputs}); @@ -72,7 +72,7 @@ TEST(Interpreter, trainASimpleNetwork) { inputs.getHandle() = {0.15, 0.15, 0.15, 0.15}; expected.getHandle() = {0.9, 0.9, 0.9, 0.9}; - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -117,7 +117,7 @@ TEST(Interpreter, simpleRegression) { auto I = inputs.getHandle(); auto E = expected.getHandle(); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -185,7 +185,7 @@ TEST(Interpreter, learnXor) { TL.at({i, 0}) = a ^ b; } - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -264,7 +264,7 @@ TEST(Network, circle) { auto *SM = G.createSoftMax("soft", RL1, S); auto *result = G.createReturn("ret", SM); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); @@ -359,7 +359,7 @@ TEST(Network, learnSingleValueConcat) { inputs.getHandle().clear(0.15); expected.getHandle().clear(0.9); - G.generateIR(); + IP.getModule().generateIR(); IP.optimize(OptimizationMode::Train); IP.initVars(); diff --git a/tests/unittests/Tensors.cpp b/tests/unittests/Tensors.cpp index 9575bcac19..be023009b7 100644 --- a/tests/unittests/Tensors.cpp +++ b/tests/unittests/Tensors.cpp @@ -1,6 +1,6 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. -#include "glow/Network/Tensor.h" +#include "glow/Base/Tensor.h" #include "gtest/gtest.h" diff --git a/tools/loader/loader.cpp b/tools/loader/loader.cpp index 37dc4c9262..0c450f1ea4 100644 --- a/tools/loader/loader.cpp +++ b/tools/loader/loader.cpp @@ -1,11 +1,11 @@ // Copyright 2017 Facebook Inc. All Rights Reserved. +#include "glow/Base/Image.h" +#include "glow/Base/Tensor.h" #include "glow/Graph/Graph.h" #include "glow/Graph/Nodes.h" #include "glow/Importer/Caffe2.h" #include "glow/Interpreter/Interpreter.h" -#include "glow/Network/Image.h" -#include "glow/Network/Tensor.h" using namespace glow;