ONE - On-device Neural Engine
Loading...
Searching...
No Matches
caffeimport::ConvolutionBuilder Class Referencefinal

#include <Convolution.h>

Collaboration diagram for caffeimport::ConvolutionBuilder:

Public Member Functions

void build (const ::caffe::LayerParameter &layer, GraphBuilderContext *context) const override
 
- Public Member Functions inherited from caffeimport::GraphBuilder
virtual ~GraphBuilder ()
 

Detailed Description

Definition at line 27 of file Convolution.h.

Member Function Documentation

◆ build()

void caffeimport::ConvolutionBuilder::build ( const ::caffe::LayerParameter &  layer,
GraphBuilderContext context 
) const
overridevirtual

Implements caffeimport::GraphBuilder.

Definition at line 37 of file Convolution.cpp.

39{
40 coco::Module *module = context->module();
41 coco::Data *data = context->data();
42 coco::Block *blk = context->block();
43 std::map<std::string, tensor::Shape> &shape_ctx = context->shape_ctx();
44 std::map<std::string, coco::Bag *> &bag_ctx = context->bag_ctx();
45 WeightContext &weight_ctx = context->weight_ctx();
46
47 assert(layer.bottom().size() == 1);
48 assert(layer.top().size() == 1);
49
50 assert(layer.has_convolution_param());
51 const auto &param = layer.convolution_param();
52
53 ConvolutionSpec spec{param};
54 {
55 const auto ifm_name = layer.bottom(0);
56 const auto ifm_shape = shape_ctx.at(ifm_name);
57 spec.ifm_shape(ifm_shape);
58 }
59
60 // NOTE The current implementation focuses on 2D convolution
61 // TODO Support general ND convolution
62 assert(spec.num_batch_axes() == 1);
63 assert(spec.num_spatial_axes() == 2);
64
65 // Create an object for an input feature map
66 const auto ifm_name = layer.bottom(0);
67 const auto ifm_shape = shape_ctx.at(ifm_name);
68 auto ifm_bag = bag_ctx.at(ifm_name);
69 auto ifm_obj = module->entity()->object()->create<coco::FeatureObject>();
70
71 ifm_obj->bag(ifm_bag);
72 ifm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ifm_shape)));
73
74 // Create an object for an output feature map
75 const auto ofm_name = layer.top(0);
76 const auto ofm_shape = spec.ofm_shape();
77 auto ofm_bag = module->entity()->bag()->create(num_elements(ofm_shape));
78 auto ofm_obj = module->entity()->object()->create<coco::FeatureObject>();
79
80 ofm_obj->bag(ofm_bag);
81 ofm_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ofm_shape)));
82
83 // Create an object for kernel
84 using namespace coco::KernelLayouts;
85
86 const auto ker_shape = spec.ker_shape();
87 auto ker_bag = module->entity()->bag()->create(num_elements(ker_shape));
88 auto ker_obj = module->entity()->object()->create<coco::KernelObject>();
89
90 ker_obj->bag(ker_bag);
91 ker_obj->layout(NCHW::create(as_kernel_shape(ker_shape)));
92
93 // Create a kernel overlay for the kernel object
94 data->f32()->allocate(ker_bag);
95
96 // Initialize the kernel overlay
97 assert(weight_ctx.blob_count(layer.name()) >= 1);
98 auto ker_blob = weight_ctx.blob_get(layer.name(), 0);
99
100 assert(ker_shape == caffeimport::as_tensor_shape(ker_blob));
101
102 auto ker_dst = data->f32()->access(ker_obj);
104 ker_obj->shape(), ker_blob->mutable_data()->begin());
105
106 for (uint32_t n = 0; n < ker_obj->shape().count(); ++n)
107 {
108 for (uint32_t ch = 0; ch < ker_obj->shape().depth(); ++ch)
109 {
110 for (uint32_t row = 0; row < ker_obj->shape().height(); ++row)
111 {
112 for (uint32_t col = 0; col < ker_obj->shape().width(); ++col)
113 {
114 ker_dst->at(n, ch, row, col) = ker_src.at(n, ch, row, col);
115 }
116 }
117 }
118 }
119
120 // Create a Load op
121 auto load = op_builder(module).load(ifm_obj).pop();
122
123 // Create a Conv2D op
124 auto op = module->entity()->op()->create<coco::Conv2D>();
125
126 op->group(spec.group());
127
128 op->ker(ker_obj);
129 op->stride()->vertical(spec.stride(0));
130 op->stride()->horizontal(spec.stride(1));
131
132 op->pad()->top(spec.pad(0));
133 op->pad()->bottom(spec.pad(0));
134 op->pad()->left(spec.pad(1));
135 op->pad()->right(spec.pad(1));
136
137 op->arg(load);
138
139 // Create an Eval instruction
140 auto ins = instr_builder(module).eval(ofm_obj, op);
141
142 // Append the instruction to the block
143 blk->instr()->append(ins);
144
145 //
146 // coco IR allows Conv2D fused with Add, but the current implementation of enco backend
147 // is unable to process such a tree.
148 //
149 // As a workaround, caffe frontend constructs a instruction for Conv2D and Add.
150 //
151 if (param.bias_term())
152 {
153 assert(weight_ctx.blob_count(layer.name()) >= 2);
154
155 // Create Bag & Object
156 auto bias_bag = module->entity()->bag()->create(ker_shape.dim(0));
157 auto bias_obj = module->entity()->object()->create<coco::FeatureObject>();
158
159 bias_obj->bag(bias_bag);
160 bias_obj->layout(coco::FeatureLayouts::BC::create(as_feature_shape(ofm_shape)));
161
162 auto added_bag = module->entity()->bag()->create(num_elements(ofm_shape));
163 auto added_obj = module->entity()->object()->create<coco::FeatureObject>();
164
165 added_obj->bag(added_bag);
166 added_obj->layout(coco::FeatureLayouts::BCHW::create(as_feature_shape(ofm_shape)));
167
168 // Create Op
169 auto bias_add = op_builder(module).load(bias_obj).load(ofm_obj).add().pop();
170
171 // Create Instr
172 auto bias_add_ins = instr_builder(module).eval(added_obj, bias_add);
173
174 // Append the instruction
175 blk->instr()->append(bias_add_ins);
176
177 // Fill bias data
178 data->f32()->allocate(bias_bag);
179
180 auto bias_span = data->f32()->weight(bias_bag);
181 auto bias_blob = weight_ctx.blob_get(layer.name(), 1);
182
183 for (uint32_t ch = 0; ch < ker_obj->shape().count(); ++ch)
184 {
185 bias_span[ch] = bias_blob->data(ch);
186 }
187
188 // Update output
189 ofm_bag = added_bag;
190 }
191
192 // Update bag and shape context
193 bag_ctx[ofm_name] = ofm_bag;
194 shape_ctx[ofm_name] = ofm_shape;
195}
OpBuilder op_builder(coco::Module *m)
Definition IRBuilder.h:144
InstrBuilder instr_builder(coco::Module *m)
Definition IRBuilder.h:174
const nncc::core::ADT::tensor::Shape & ifm_shape(void) const
coco::Eval * eval(coco::Object *out, coco::Op *op) const
Create "Eval" instruction with a given "Object" and "Op".
Definition IRBuilder.h:162
OpBuilder & load(coco::Object *obj)
Create "Load" op and push it onto the internal stack.
Definition IRBuilder.h:70
coco::Op * pop(void)
Pop op from the internal stack.
Definition IRBuilder.h:116
OpBuilder & add(void)
Create "Add" op and push it onto the internal stack.
Definition IRBuilder.h:84
A unit of (grouped) instructions.
Definition Block.h:40
InstrList * instr(void)
Definition Block.h:65
void append(Child *child)
static std::unique_ptr< BCHW > create(const nncc::core::ADT::feature::Shape &shape)
static std::unique_ptr< BC > create(const nncc::core::ADT::feature::Shape &shape)
Top-level element of coco IR which represents a neural network.
Definition Module.h:34
tensor::Shape as_tensor_shape(const ::caffe::BlobShape &blob_shape)
Definition Convert.cpp:24
nncc::core::ADT::feature::Shape as_feature_shape(const nncc::core::ADT::tensor::Shape &)
Definition caffe.cpp:54
nncc::core::ADT::kernel::Shape as_kernel_shape(const nncc::core::ADT::tensor::Shape &)
Definition caffe.cpp:61
TensorSignatures load(const char *info_path)
Function to create TensorSignatures defined in info file.
Core coco entity for constant weights.
Definition Data.h:31
virtual Op * arg(uint32_t n) const =0
Return N-th argument.
static Overlay< T, InputIt > make(const Shape &shape, InputIt it)
Definition Overlay.h:65

References OpBuilder::add(), coco::DLinkedList< Child, Parent >::Head::append(), coco::Op::arg(), morph::caffe::as_feature_shape(), morph::caffe::as_kernel_shape(), caffeimport::as_tensor_shape(), caffeimport::GraphBuilderContext::bag_ctx(), caffeimport::WeightContext::blob_count(), caffeimport::WeightContext::blob_get(), caffeimport::GraphBuilderContext::block(), coco::FeatureLayouts::BCHW::create(), coco::FeatureLayouts::BC::create(), caffeimport::GraphBuilderContext::data(), InstrBuilder::eval(), ConvolutionSpec::ifm_shape(), coco::Block::instr(), instr_builder(), OpBuilder::load(), nncc::core::ADT::kernel::OverlayFactory< T, LayoutImpl >::make(), op_builder(), OpBuilder::pop(), caffeimport::GraphBuilderContext::shape_ctx(), and caffeimport::GraphBuilderContext::weight_ctx().


The documentation for this class was generated from the following files: