1 #include "caffe2/opt/fusion.h" 2 #include "caffe2/core/logging.h" 3 #include "caffe2/opt/converter.h" 4 #include "caffe2/opt/passes.h" 20 for (
auto node_pair : repr::nn::dataIterator<repr::Conv>(nn->dataFlow)) {
23 std::tie(conv, convNode) = node_pair;
25 auto output = repr::nn::getOutputs(convNode).front();
26 auto consumers = repr::nn::getConsumers(output);
27 NOM_REQUIRE_OR_CONT(consumers.size() == 1);
29 auto consumer = consumers.front();
30 NOM_REQUIRE_OR_CONT(repr::nn::is<repr::BatchNormalization>(consumer));
32 auto bnNode = consumer;
33 auto bn = repr::nn::get<repr::BatchNormalization>(bnNode);
34 auto bnOutputs = nn::getOutputs(bnNode);
35 NOM_REQUIRE_OR_CONT(bnOutputs.size() == 1);
36 auto bnOutput = bnOutputs.front();
38 auto convInputs = repr::nn::getInputs(convNode);
39 if (convInputs.size() < 2) {
43 auto bnInputs = repr::nn::getInputs(bnNode);
45 bnInputs.size() >= 5,
"Invalid batch normalization input size");
47 #define EXPOSE_TENSOR_DATA(name, index, inputs) \ 48 auto name = repr::nn::get<repr::Tensor>(inputs[index]); \ 49 assert(ws->HasBlob(name->getName()) && "Blob not in workspace"); \ 50 auto name##Tensor = BlobGetMutableTensor(ws->GetBlob(name->getName()), CPU); \ 51 auto name##Data = name##Tensor->mutable_data<float>(); 53 EXPOSE_TENSOR_DATA(filter, 1, convInputs);
55 EXPOSE_TENSOR_DATA(scale, 1, bnInputs);
56 EXPOSE_TENSOR_DATA(biasBN, 2, bnInputs);
57 EXPOSE_TENSOR_DATA(mean, 3, bnInputs);
58 EXPOSE_TENSOR_DATA(variance, 4, bnInputs);
60 if (convInputs.size() == 2) {
61 NOM_REQUIRE_OR_CONT(conv->getMutableAnnotation() !=
nullptr);
64 NOM_REQUIRE_OR_CONT(annotation !=
nullptr);
65 auto op = annotation->getOperatorDef();
66 auto convName = op.name();
69 auto convBiasName = convName +
"_bias" + to_string(convOrder);
70 if (!ws->
HasBlob(convBiasName)) {
71 auto convBiasTensor = make_unique<repr::Tensor>(convBiasName);
72 convBiasTensor->setType(repr::Tensor::DataType::Float);
74 unique_dyn_cast<repr::NeuralNetData>(convBiasTensor));
75 nn->inputs.insert(convBiasNode);
76 nn->dataFlow.
createEdge(convBiasNode, convNode);
80 CHECK_NOTNULL(tensor);
82 size_t c = filterTensor->dim32(0);
84 float* tensor_data = tensor->mutable_data<
float>();
85 memset(tensor_data, 0, tensor->nbytes());
92 convInputs = repr::nn::getInputs(convNode);
93 EXPOSE_TENSOR_DATA(biasConv, 2, convInputs);
95 #undef EXPOSE_TENSOR_DATA 98 auto chwDim = filterTensor->size_from_dim(1);
99 for (
auto c = 0; c < filterTensor->dim32(0); ++c) {
101 scaleData[c] / std::sqrt(varianceData[c] + bn->getEpsilon());
102 for (
auto i = 0; i < chwDim; ++i) {
103 filterData[c * chwDim + i] *= coeff;
105 auto bias = (biasConvData[c] - meanData[c]) * coeff + biasBNData[c];
106 biasConvData[c] = bias;
118 while (fuseConvBNHelper(nn, ws)) {
122 REGISTER_WS_OPT_PASS_FROM_FUNC(FuseConvBN, fuseConvBN);
Blob * CreateBlob(const string &name)
Creates a blob of the given name.
NodeRef createNode(T &&data)
Creates a node and retains ownership of it.
Workspace is a class that holds all the related objects created during runtime: (1) all blobs...
A global dictionary that holds information about what Caffe2 modules have been loaded in the current ...
void deleteNode(NodeRef n)
Deletes a node from the graph.
bool HasBlob(const string &name) const
Checks if a blob with the given name is present in the current workspace.
EdgeRef createEdge(NodeRef tail, NodeRef head, U...data)
Creates a directed edge and retains ownership of it.