From 25a353f56bb3f03e659d04e7551f0763bdf2a2e6 Mon Sep 17 00:00:00 2001
From: "A. Unique TensorFlower" <gardener@tensorflow.org>
Date: Wed, 7 Dec 2016 14:48:37 -0800
Subject: [PATCH] Add sub makefile to execute inference on hexagon Change:
 141360232

---
 .../hexagon_graph_execution/Makefile.in       | 74 +++++++++++++++++++
 .../sub_makefiles/quantization/Makefile.in    | 12 +--
 .../core/kernels/hexagon/graph_transferer.cc  | 22 ++++--
 .../hexagon/hexagon_graph_execution_test.cc   |  8 +-
 4 files changed, 103 insertions(+), 13 deletions(-)
 create mode 100644 tensorflow/contrib/makefile/sub_makefiles/hexagon_graph_execution/Makefile.in

diff --git a/tensorflow/contrib/makefile/sub_makefiles/hexagon_graph_execution/Makefile.in b/tensorflow/contrib/makefile/sub_makefiles/hexagon_graph_execution/Makefile.in
new file mode 100644
index 00000000000..a4cf5f70cde
--- /dev/null
+++ b/tensorflow/contrib/makefile/sub_makefiles/hexagon_graph_execution/Makefile.in
@@ -0,0 +1,74 @@
+#!/usr/bin/env bash
+# Copyright 2016 The TensorFlow Authors. 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.
+# ==============================================================================
+# This sub Makefile compiles libraries under this directory. This is designed to
+# be used as a sub Makefile with tensorflow/contrib/makefile/Makefile.
+# You can build targets in this file by including this sub makefile like:
+# $ make -f tensorflow/contrib/makefile/Makefile TARGET=<target> \
+# SUB_MAKEFILES=\
+# $(pwd)/tensorflow/contrib/makefile/sub_makefiles/hexagon_graph_execution/Makefile.in \
+# (optional: NDK_ROOT=<ndk_root>) hexagon_graph_execution
+# TODO(satok): Support more targets
+
+GTEST_DIR := \
+$(MAKEFILE_DIR)/downloads/googletest/googletest
+
+GTEST_HEADERS = \
+$(wildcard $(GTEST_DIR)/include/gtest/*.h) \
+$(wildcard $(GTEST_DIR)/include/gtest/internal/*.h)
+
+GTEST_SRCS := \
+$(wildcard $(GTEST_DIR)/src/*.cc) \
+$(wildcard $(GTEST_DIR)/src/*.h) \
+$(GTEST_HEADERS)
+
+# CAVEAT: We should disable TENSORFLOW_DISABLE_META while running
+# quantized_matmul on Android because it crashes in
+# MultiThreadGemm in tensorflow/core/kernels/meta_support.cc
+# TODO(satok): Remove once it's fixed
+CXXFLAGS += -DTENSORFLOW_DISABLE_META
+
+GRAPH_EXECUTION_SRCS := \
+tensorflow/core/kernels/hexagon/graph_transferer.cc \
+tensorflow/core/kernels/hexagon/hexagon_control_wrapper.cc \
+tensorflow/core/kernels/hexagon/hexagon_ops_definitions.cc \
+tensorflow/core/kernels/hexagon/hexagon_graph_execution_test.cc \
+tensorflow/contrib/makefile/test/test_main.cc
+
+GRAPH_EXECUTION_OBJS := $(addprefix $(OBJDIR), $(GRAPH_EXECUTION_SRCS:.cc=.o))
+
+GRAPH_EXECUTION_NAME := hexagon_graph_execution
+GRAPH_EXECUTION_BIN_PATH := $(BINDIR)$(GRAPH_EXECUTION_NAME)
+
+INCLUDES += \
+-I$(MAKEFILE_DIR)/downloads/googletest/googletest/include
+
+GRAPH_EXECUTION_INCLUDES := $(INCLUDES)
+
+$(OBJDIR)gtest-all.o: $(GTEST_SRCS) $(GRAPH_EXECUTION_OBJS)
+	$(CXX) $(CXXFLAGS) $(GRAPH_EXECUTION_INCLUDES) -I $(GTEST_DIR) -c \
+	$(GTEST_DIR)/src/gtest-all.cc -o $@
+
+$(LIBDIR)gtest.a: $(OBJDIR)gtest-all.o
+	@mkdir -p $(dir $@)
+	$(AR) $(ARFLAGS) $@ $^
+
+$(GRAPH_EXECUTION_BIN_PATH): $(LIB_PATH) $(LIBDIR)gtest.a $(GRAPH_EXECUTION_OBJS)
+	@mkdir -p $(dir $@)
+	$(CXX) $(CXXFLAGS) $(GRAPH_EXECUTION_INCLUDES) \
+		-o $(GRAPH_EXECUTION_BIN_PATH) $(GRAPH_EXECUTION_OBJS) \
+		$(LIBFLAGS) $(LIB_PATH) $(LIBDIR)gtest.a $(LDFLAGS) $(LIBS)
+
+$(GRAPH_EXECUTION_NAME): $(GRAPH_EXECUTION_BIN_PATH)
diff --git a/tensorflow/contrib/makefile/sub_makefiles/quantization/Makefile.in b/tensorflow/contrib/makefile/sub_makefiles/quantization/Makefile.in
index baf285268c0..ef419136638 100644
--- a/tensorflow/contrib/makefile/sub_makefiles/quantization/Makefile.in
+++ b/tensorflow/contrib/makefile/sub_makefiles/quantization/Makefile.in
@@ -34,12 +34,13 @@ $(wildcard $(GTEST_DIR)/src/*.cc) \
 $(wildcard $(GTEST_DIR)/src/*.h) \
 $(GTEST_HEADERS)
 
+# CAVEAT: We should disable TENSORFLOW_DISABLE_META while running
+# quantized_matmul on Android because it crashes in
+# MultiThreadGemm in tensorflow/core/kernels/meta_support.cc
+# TODO(satok): Remove once it's fixed
+CXXFLAGS += -DTENSORFLOW_DISABLE_META
+
 QUANTIZATION_TEST_SRCS := \
-tensorflow/core/ops/math_ops.cc \
-tensorflow/core/kernels/quantize_op.cc \
-tensorflow/core/kernels/quantized_conv_ops.cc \
-tensorflow/core/kernels/quantized_matmul_op.cc \
-tensorflow/core/kernels/quantized_matmul_op_test.cc \
 tensorflow/core/kernels/hexagon/quantized_matmul_op_for_hexagon_test.cc \
 tensorflow/contrib/makefile/test/test_main.cc
 
@@ -59,6 +60,7 @@ $(OBJDIR)gtest-all.o: $(GTEST_SRCS) $(QUANTIZATION_TEST_OBJS)
 	$(GTEST_DIR)/src/gtest-all.cc -o $@
 
 $(LIBDIR)gtest.a: $(OBJDIR)gtest-all.o
+	@mkdir -p $(dir $@)
 	$(AR) $(ARFLAGS) $@ $^
 
 $(QUANTIZATION_TEST_BIN_PATH): $(LIB_PATH) $(LIBDIR)gtest.a $(QUANTIZATION_TEST_OBJS)
diff --git a/tensorflow/core/kernels/hexagon/graph_transferer.cc b/tensorflow/core/kernels/hexagon/graph_transferer.cc
index 352c2c63f0d..700521618c4 100644
--- a/tensorflow/core/kernels/hexagon/graph_transferer.cc
+++ b/tensorflow/core/kernels/hexagon/graph_transferer.cc
@@ -48,6 +48,15 @@ const string PADDING_SAME_STR = "SAME";
 const string PADDING_NA = "NA";
 const string NULL_OUTPUT_NAME = "NULL";
 
+// This is a temporary workaround to support android build
+// where std::string is not supported even with c++11 option.
+template <typename T>
+static string ToString(T val) {
+  std::stringstream stream;
+  stream << val;
+  return stream.str();
+}
+
 /**
  * graph loading functions
  * - LoadGraphFromProto
@@ -363,7 +372,7 @@ void GraphTransferer::RegisterConstantNode(
   VLOG(1) << "Register constant node: " << node.name();
   CHECK(node_name_to_id_cache_map_.count(node.name()) == 1);
   const int id = node_name_to_id_cache_map_[node.name()];
-  const string data_name = DATA_NODE_PREFIX + std::to_string(id);
+  const string data_name = DATA_NODE_PREFIX + ToString(id);
   const int output_node_size = node.num_outputs();
   CHECK(output_node_size == 1);
   // TODO(satok): support multiple outputs?
@@ -404,10 +413,9 @@ int GraphTransferer::RegisterConstantShape(const std::vector<int>& shape) {
   VLOG(1) << "Cache constant shape.";
   // TODO(satok): Handle non-4dim strides
   CHECK(shape.size() == 4);
-  const string shape_name = CONST_SHAPE_PREFIX + std::to_string(shape.at(0)) +
-                            'x' + std::to_string(shape.at(1)) + 'x' +
-                            std::to_string(shape.at(2)) + 'x' +
-                            std::to_string(shape.at(3));
+  const string shape_name = CONST_SHAPE_PREFIX + ToString(shape.at(0)) + 'x' +
+                            ToString(shape.at(1)) + 'x' +
+                            ToString(shape.at(2)) + 'x' + ToString(shape.at(3));
   if (node_name_to_id_cache_map_.count(shape_name) <= 0) {
     node_name_cache_list_.emplace_back(nullptr);
     const int id = node_name_cache_list_.size() - 1;
@@ -589,10 +597,10 @@ void GraphTransferer::AppendNodeParams(const string& name, const int id,
                                        const int outputs_size) {
   VLOG(1) << "Append node params: " << name;
   // TODO(satok): store padding as Padding?
-  const string output_name = OUTPUTS_NODE_PREFIX + std::to_string(id);
+  const string output_name = OUTPUTS_NODE_PREFIX + ToString(id);
   node_transfer_params_list_.emplace_back(
       NodeTransferParams{name, id, type, type_id, PADDING_PREFIX + padding_str,
-                         INPUTS_NODE_PREFIX + std::to_string(id),
+                         INPUTS_NODE_PREFIX + ToString(id),
                          inputs_size + static_cast<int>(extra_inputs.size()),
                          outputs_size <= 0 ? NULL_OUTPUT_NAME : output_name,
                          static_cast<int>(outputs_size)});
diff --git a/tensorflow/core/kernels/hexagon/hexagon_graph_execution_test.cc b/tensorflow/core/kernels/hexagon/hexagon_graph_execution_test.cc
index 02733bf1b15..2444b93850c 100644
--- a/tensorflow/core/kernels/hexagon/hexagon_graph_execution_test.cc
+++ b/tensorflow/core/kernels/hexagon/hexagon_graph_execution_test.cc
@@ -12,6 +12,9 @@ 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.
 ==============================================================================*/
+// Before calling this test program, download a model as follows.
+// $ curl https://storage.googleapis.com/download.tensorflow.org/models/tensorflow_inception_v3_stripped_optimized_quantized.pb \
+// -o /tmp/tensorflow_inception_v3_stripped_optimized_quantized.pb
 
 #include <memory>
 
@@ -26,9 +29,12 @@ limitations under the License.
 
 namespace tensorflow {
 
+// CAVEAT: This test only runs when you specify hexagon library using
+// makefile.
+// TODO(satok): Make this generic so that this can run without any
+// additionanl steps.
 #ifdef USE_HEXAGON_LIBS
 TEST(GraphTransferer, RunInceptionV3OnHexagonExample) {
-  // Change file path to absolute path of model file on your local machine
   const string filename =
       "/tmp/tensorflow_inception_v3_stripped_optimized_quantized.pb";
   const IGraphTransferOpsDefinitions* ops_definitions =