[enco] Introduce Global Data Generation Pass (#1739)
author박종현/동작제어Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Thu, 4 Oct 2018 02:55:23 +0000 (11:55 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Thu, 4 Oct 2018 02:55:23 +0000 (11:55 +0900)
This commit extracts code related with global weight array generation,
and introduces "Global Data Generation" pass that includes the extracted code.

Signed-off-by: Jonghyun Park <jh1302.park@samsung.com>
contrib/enco/core/src/Backend.cpp
contrib/enco/core/src/CppCode.cpp
contrib/enco/core/src/Transforms/GlobalDataGeneration.cpp [new file with mode: 0644]
contrib/enco/core/src/Transforms/GlobalDataGeneration.h [new file with mode: 0644]

index d11bd44..4270d3d 100644 (file)
@@ -32,6 +32,7 @@
 #include "Transforms/DeadBagElimination.h"
 #include "Transforms/Optimizations.h"
 #include "Transforms/Split.h"
+#include "Transforms/GlobalDataGeneration.h"
 
 #include "Lower.h"
 
@@ -128,6 +129,8 @@ void BackendImpl::compile(coco::Module *m, coco::Data *d)
   SplitPass split;
   split.runOnCode(code(sess));
 
+  generate_global_data(code(sess));
+
   // TODO Run various transforms over enco::Code
 
   std::ofstream ofs{_prefix + ".cpp"};
index 459b7b7..512ce80 100644 (file)
@@ -16,6 +16,8 @@
 
 #include "CppCode.h"
 
+#include "Transforms/GlobalDataGeneration.h"
+
 #include "CppGen/Global.h"
 #include "CppGen/MemoryContext.h"
 
@@ -92,7 +94,6 @@ void CppCode::dump(std::ostream &os) const
 {
   auto m = _code->module();
 
-  Global global;
   NetworkStruct network;
   InvokeFunction invoke;
   pp::LinearDocument internal;
@@ -134,13 +135,11 @@ void CppCode::dump(std::ostream &os) const
     auto subnet_field_name = pp::fmt("_subnet_", subnet_ctx.size());
 
     // Create global data variable
-    auto emit_weight = [&](const ann::OperandID &id, const ann::Operand *info) {
+    auto emit_weight = [&](const ann::OperandID &, const ann::Operand *info) {
       if (info->weight())
       {
-        auto base = info->weight()->base();
         auto size = info->weight()->size();
-        auto off = global.constant(base, size);
-
+        auto off = enco::GlobalData::data_offset(info);
         auto base_exp = pp::fmt("reinterpret_cast<const void *>(", data_exp(off), ")");
         auto size_exp = pp::fmt(size);
 
@@ -314,9 +313,9 @@ void CppCode::dump(std::ostream &os) const
       auto input = m->input()->at(n);
       auto dims = as_dims(input->shape());
 
-      auto name_off = global.constant(input->name());
+      auto name_off = enco::GlobalData::name_offset(input);
       auto name_exp = pp::fmt("reinterpret_cast<const char *>(", data_exp(name_off), ")");
-      auto dims_off = global.constant<uint32_t>(dims);
+      auto dims_off = enco::GlobalData::dims_offset(input);
       auto dims_exp = pp::fmt("reinterpret_cast<const unsigned *>(", data_exp(dims_off), ")");
 
       net_ctor.append("inputs.at(", n, ").name = ", name_exp, ";");
@@ -330,9 +329,9 @@ void CppCode::dump(std::ostream &os) const
       auto output = m->output()->at(n);
       auto dims = as_dims(output->shape());
 
-      auto name_off = global.constant(output->name());
+      auto name_off = enco::GlobalData::name_offset(output);
       auto name_exp = pp::fmt("reinterpret_cast<const char *>(", data_exp(name_off), ")");
-      auto dims_off = global.constant<uint32_t>(dims);
+      auto dims_off = enco::GlobalData::dims_offset(output);
       auto dims_exp = pp::fmt("reinterpret_cast<const unsigned *>(", data_exp(dims_off), ")");
 
       net_ctor.append("outputs.at(", n, ").name = ", name_exp, ";");
@@ -358,7 +357,7 @@ void CppCode::dump(std::ostream &os) const
 
   source.append(includes);
   source.append();
-  source.append("uint8_t ", data_varname, "[] = { ", global, " };");
+  source.append("uint8_t ", data_varname, "[] = { ", *enco::GlobalData::global(m), " };");
   source.append();
 
   source.append("namespace");
diff --git a/contrib/enco/core/src/Transforms/GlobalDataGeneration.cpp b/contrib/enco/core/src/Transforms/GlobalDataGeneration.cpp
new file mode 100644 (file)
index 0000000..76a5f7e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GlobalDataGeneration.h"
+#include "Dims.h"
+
+#include <nncc/foundation/Memory.h>
+
+#include <map>
+
+using nncc::foundation::make_unique;
+
+namespace
+{
+
+std::map<const coco::Module *, std::unique_ptr<enco::Global>> global_ctx;
+std::map<const ann::Operand *, enco::GlobalOffset> data_offset_ctx;
+std::map<const coco::Arg *, enco::GlobalOffset> name_offset_ctx;
+std::map<const coco::Arg *, enco::GlobalOffset> dims_offset_ctx;
+
+} // namespace
+
+namespace enco
+{
+
+const Global *GlobalData::global(const coco::Module *m) { return global_ctx.at(m).get(); }
+
+GlobalOffset GlobalData::data_offset(const ann::Operand *o) { return data_offset_ctx.at(o); }
+
+GlobalOffset GlobalData::name_offset(const coco::Input *in) { return name_offset_ctx.at(in); }
+GlobalOffset GlobalData::dims_offset(const coco::Input *in) { return dims_offset_ctx.at(in); }
+
+GlobalOffset GlobalData::name_offset(const coco::Output *out) { return name_offset_ctx.at(out); }
+GlobalOffset GlobalData::dims_offset(const coco::Output *out) { return dims_offset_ctx.at(out); }
+
+void generate_global_data(enco::Code *code)
+{
+  auto m = code->module();
+  auto global = make_unique<Global>();
+
+  for (uint32_t n = 0; n < code->ann()->count(); ++n)
+  {
+    auto binder = code->ann()->nth(n);
+
+    auto emit = [&](const ann::OperandID &id, const ann::Operand *info) {
+      if (info->weight())
+      {
+        auto base = info->weight()->base();
+        auto size = info->weight()->size();
+
+        data_offset_ctx[info] = global->constant(base, size);
+      }
+    };
+    binder->module()->operand()->each(emit);
+  }
+
+  for (uint32_t n = 0; n < m->input()->size(); ++n)
+  {
+    auto input = m->input()->at(n);
+    auto dims = as_dims(input->shape());
+
+    name_offset_ctx[input] = global->constant(input->name());
+    dims_offset_ctx[input] = global->constant<uint32_t>(dims);
+  }
+
+  for (uint32_t n = 0; n < m->output()->size(); ++n)
+  {
+    auto output = m->output()->at(n);
+    auto dims = as_dims(output->shape());
+
+    name_offset_ctx[output] = global->constant(output->name());
+    dims_offset_ctx[output] = global->constant<uint32_t>(dims);
+  }
+
+  global_ctx[m] = std::move(global);
+}
+
+} // namespace enco
diff --git a/contrib/enco/core/src/Transforms/GlobalDataGeneration.h b/contrib/enco/core/src/Transforms/GlobalDataGeneration.h
new file mode 100644 (file)
index 0000000..418f1dd
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __ENCO_TRANSFORM_GLOBAL_DATA_GENERATION_H__
+#define __ENCO_TRANSFORM_GLOBAL_DATA_GENERATION_H__
+
+#include "CppGen/Global.h"
+#include "Code.h"
+
+namespace enco
+{
+
+struct GlobalData
+{
+  static const Global *global(const coco::Module *);
+
+  static GlobalOffset data_offset(const ann::Operand *);
+  static GlobalOffset name_offset(const coco::Input *);
+  static GlobalOffset dims_offset(const coco::Input *);
+  static GlobalOffset name_offset(const coco::Output *);
+  static GlobalOffset dims_offset(const coco::Output *);
+};
+
+/**
+ * @brief Generate 'Global' weight array.
+ *
+ * NOTE Succeeding passes can access offsets via "GlobalData"
+ */
+void generate_global_data(enco::Code *);
+
+} // namespace enco
+
+#endif // __ENCO_TRANSFORM_GLOBAL_DATA_GENERATION_H__