aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--tensorflow/compiler/xla/service/cpu/BUILD16
-rw-r--r--tensorflow/compiler/xla/service/cpu/compiler_functor.cc17
-rw-r--r--tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.cc6
-rw-r--r--tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h2
-rw-r--r--tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.cc7
-rw-r--r--tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h3
-rw-r--r--tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.cc140
-rw-r--r--tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.h42
-rw-r--r--tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc2
-rw-r--r--tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc44
-rw-r--r--tensorflow/core/ops/ops.pbtxt2
-rw-r--r--tensorflow/docs_src/deploy/index.md5
-rw-r--r--tensorflow/docs_src/deploy/leftnav_files1
-rw-r--r--tensorflow/docs_src/deploy/tfserve.md30
-rw-r--r--tensorflow/docs_src/programmers_guide/leftnav_files2
-rw-r--r--tensorflow/docs_src/programmers_guide/saved_model.md4
-rw-r--r--tensorflow/go/op/wrappers.go2
-rw-r--r--tensorflow/java/maven/run_inside_container.sh45
-rw-r--r--tensorflow/java/maven/tensorflow-android/pom-android.xml.template29
-rw-r--r--tensorflow/java/maven/tensorflow-android/update.py139
20 files changed, 467 insertions, 71 deletions
diff --git a/tensorflow/compiler/xla/service/cpu/BUILD b/tensorflow/compiler/xla/service/cpu/BUILD
index 2ca4af67cd..06647a7bbc 100644
--- a/tensorflow/compiler/xla/service/cpu/BUILD
+++ b/tensorflow/compiler/xla/service/cpu/BUILD
@@ -285,6 +285,7 @@ cc_library(
":cpu_runtime_avx",
":cpu_runtime_sse4_1",
":disassembler",
+ ":llvm_ir_runtime",
"//tensorflow/compiler/xla:statusor",
"//tensorflow/compiler/xla:types",
"//tensorflow/compiler/xla:util",
@@ -346,6 +347,21 @@ cc_library(
)
cc_library(
+ name = "llvm_ir_runtime",
+ srcs = [
+ "llvm_ir_runtime.cc",
+ ],
+ hdrs = [
+ "llvm_ir_runtime.h",
+ ],
+ deps = [
+ "//tensorflow/core:lib",
+ "@llvm//:core",
+ "@llvm//:transform_utils",
+ ],
+)
+
+cc_library(
name = "runtime_conv2d",
srcs = [
"runtime_conv2d.cc",
diff --git a/tensorflow/compiler/xla/service/cpu/compiler_functor.cc b/tensorflow/compiler/xla/service/cpu/compiler_functor.cc
index 7304953249..2442a0f5dc 100644
--- a/tensorflow/compiler/xla/service/cpu/compiler_functor.cc
+++ b/tensorflow/compiler/xla/service/cpu/compiler_functor.cc
@@ -39,6 +39,7 @@ limitations under the License.
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h"
#include "tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h"
+#include "tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.h"
#include "tensorflow/compiler/xla/service/llvm_ir/llvm_util.h"
#include "tensorflow/compiler/xla/statusor.h"
#include "tensorflow/compiler/xla/types.h"
@@ -84,6 +85,8 @@ operator()(llvm::Module& module) const {
CHECK(!llvm::verifyModule(module, &llvm::dbgs()));
+ runtime::RewriteIRRuntimeFunctions(&module);
+
// Buffer for holding machine code prior to constructing the ObjectFile.
llvm::SmallVector<char, 0> stream_buffer;
llvm::raw_svector_ostream ostream(stream_buffer);
@@ -136,9 +139,6 @@ std::vector<llvm::VecDesc> VectorFunctionsForTargetLibraryInfoImpl(
{"logf", runtime::kLogV4F32SymbolName, 4},
{"llvm.log.f32", runtime::kLogV4F32SymbolName, 4},
-
- {"tanhf", runtime::kTanhV4F32SymbolName, 4},
- {"llvm.tanh.f32", runtime::kTanhV4F32SymbolName, 4},
};
const llvm::VecDesc eight_wide_vector_functions[] = {
@@ -147,6 +147,13 @@ std::vector<llvm::VecDesc> VectorFunctionsForTargetLibraryInfoImpl(
{"logf", runtime::kLogV8F32SymbolName, 8},
{"llvm.log.f32", runtime::kLogV8F32SymbolName, 8},
+ };
+
+ // These functions are generated by XLA as LLVM IR, so they're always
+ // available.
+ const llvm::VecDesc ir_vector_functions[] = {
+ {"tanhf", runtime::kTanhV4F32SymbolName, 4},
+ {"llvm.tanh.f32", runtime::kTanhV4F32SymbolName, 4},
{"tanhf", runtime::kTanhV8F32SymbolName, 8},
{"llvm.tanh.f32", runtime::kTanhV8F32SymbolName, 8},
@@ -169,6 +176,10 @@ std::vector<llvm::VecDesc> VectorFunctionsForTargetLibraryInfoImpl(
std::end(eight_wide_vector_functions));
}
}
+
+ vector_functions.insert(vector_functions.end(),
+ std::begin(ir_vector_functions),
+ std::end(ir_vector_functions));
return vector_functions;
}
} // namespace
diff --git a/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.cc b/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.cc
index f6664bb854..9d8e67897c 100644
--- a/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.cc
+++ b/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.cc
@@ -29,11 +29,6 @@ xla::cpu::runtime::V8F32 __xla_cpu_runtime_LogV8F32(
xla::cpu::runtime::V8F32 x) {
return Eigen::internal::plog(x);
}
-
-xla::cpu::runtime::V8F32 __xla_cpu_runtime_TanhV8F32(
- xla::cpu::runtime::V8F32 x) {
- return Eigen::internal::ptanh(x);
-}
#endif // __AVX__
namespace xla {
@@ -42,7 +37,6 @@ namespace runtime {
const char *const kExpV8F32SymbolName = "__xla_cpu_runtime_ExpV8F32";
const char *const kLogV8F32SymbolName = "__xla_cpu_runtime_LogV8F32";
-const char *const kTanhV8F32SymbolName = "__xla_cpu_runtime_TanhV8F32";
} // namespace runtime
} // namespace cpu
diff --git a/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h b/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h
index c15710fb00..62e352f1e4 100644
--- a/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h
+++ b/tensorflow/compiler/xla/service/cpu/cpu_runtime_avx.h
@@ -48,8 +48,6 @@ xla::cpu::runtime::V8F32 __xla_cpu_runtime_ExpV8F32(xla::cpu::runtime::V8F32 x)
xla::cpu::runtime::V8F32 __xla_cpu_runtime_LogV8F32(xla::cpu::runtime::V8F32 x)
TF_ATTRIBUTE_WEAK;
-xla::cpu::runtime::V8F32 __xla_cpu_runtime_TanhV8F32(xla::cpu::runtime::V8F32 x)
- TF_ATTRIBUTE_WEAK;
}
#endif // TENSORFLOW_COMPILER_XLA_SERVICE_CPU_CPU_RUNTIME_AVX_H_
diff --git a/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.cc b/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.cc
index 58ec9fc6e8..93a1a3a3c3 100644
--- a/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.cc
+++ b/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.cc
@@ -33,12 +33,6 @@ xla::cpu::runtime::V4F32 __xla_cpu_runtime_LogV4F32(
return Eigen::internal::plog(p);
}
-xla::cpu::runtime::V4F32 __xla_cpu_runtime_TanhV4F32(
- xla::cpu::runtime::V4F32 x) {
- Eigen::internal::Packet4f p = x;
- return Eigen::internal::ptanh(p);
-}
-
#endif // __SSE4_1__
namespace xla {
@@ -47,7 +41,6 @@ namespace runtime {
const char *const kExpV4F32SymbolName = "__xla_cpu_runtime_ExpV4F32";
const char *const kLogV4F32SymbolName = "__xla_cpu_runtime_LogV4F32";
-const char *const kTanhV4F32SymbolName = "__xla_cpu_runtime_TanhV4F32";
} // namespace runtime
} // namespace cpu
diff --git a/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h b/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h
index 7ab9a52d00..591682a943 100644
--- a/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h
+++ b/tensorflow/compiler/xla/service/cpu/cpu_runtime_sse4_1.h
@@ -48,9 +48,6 @@ xla::cpu::runtime::V4F32 __xla_cpu_runtime_ExpV4F32(xla::cpu::runtime::V4F32 x)
xla::cpu::runtime::V4F32 __xla_cpu_runtime_LogV4F32(xla::cpu::runtime::V4F32 x)
TF_ATTRIBUTE_WEAK;
-
-xla::cpu::runtime::V4F32 __xla_cpu_runtime_TanhV4F32(xla::cpu::runtime::V4F32 x)
- TF_ATTRIBUTE_WEAK;
}
#endif // TENSORFLOW_COMPILER_XLA_SERVICE_CPU_CPU_RUNTIME_SSE4_1_H_
diff --git a/tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.cc b/tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.cc
new file mode 100644
index 0000000000..77e4425aa2
--- /dev/null
+++ b/tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.cc
@@ -0,0 +1,140 @@
+/* Copyright 2017 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.
+==============================================================================*/
+
+#include "tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.h"
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "tensorflow/core/platform/logging.h"
+
+namespace xla {
+namespace cpu {
+namespace runtime {
+
+const char* const kTanhV4F32SymbolName = "__xla_cpu_runtime_TanhV4F32";
+const char* const kTanhV8F32SymbolName = "__xla_cpu_runtime_TanhV8F32";
+
+namespace {
+llvm::Function* EmitVectorF32TanhIfNeeded(llvm::Module* module,
+ llvm::StringRef function_name,
+ int vector_width) {
+ llvm::Function* vector_tanh_function = module->getFunction(function_name);
+ if (vector_tanh_function == nullptr) {
+ // If the function declaration is not present in the module, there can't be
+ // any calls to resolve. Don't emit the function in this case.
+ return nullptr;
+ }
+
+ llvm::LLVMContext* context = &module->getContext();
+ llvm::Type* float_type = llvm::Type::getFloatTy(*context);
+ llvm::VectorType* vector_type =
+ llvm::VectorType::get(float_type, vector_width);
+
+ llvm::Function* min_intrinsic = llvm::Intrinsic::getDeclaration(
+ module, llvm::Intrinsic::minnum, vector_type);
+ llvm::Function* max_intrinsic = llvm::Intrinsic::getDeclaration(
+ module, llvm::Intrinsic::maxnum, vector_type);
+
+ llvm::BasicBlock* vector_tanh_body =
+ llvm::BasicBlock::Create(*context, "body", vector_tanh_function);
+
+ llvm::IRBuilder<> ir_builder(vector_tanh_body);
+
+ llvm::FastMathFlags fast_math_flags;
+ fast_math_flags.setUnsafeAlgebra();
+ ir_builder.setFastMathFlags(fast_math_flags);
+
+ llvm::Value* input = &*vector_tanh_function->arg_begin();
+ CHECK_EQ(input->getType(), vector_type);
+
+ // This implements the same rational interpolant as implemented in Eigen3.
+ llvm::Value* input_clamped = ir_builder.CreateCall(
+ min_intrinsic,
+ {ir_builder.CreateCall(max_intrinsic,
+ {input, llvm::ConstantFP::get(vector_type, -9.0)}),
+ llvm::ConstantFP::get(vector_type, 9.0)});
+
+ std::array<float, 7> numerator_coeffs(
+ {{-2.76076847742355e-16f, 2.00018790482477e-13f, -8.60467152213735e-11f,
+ 5.12229709037114e-08f, 1.48572235717979e-05f, 6.37261928875436e-04f,
+ 4.89352455891786e-03f}});
+
+ std::array<float, 4> denominator_coeffs(
+ {{1.19825839466702e-06f, 1.18534705686654e-04f, 2.26843463243900e-03f,
+ 4.89352518554385e-03f}});
+
+ llvm::Value* input_squared =
+ ir_builder.CreateFMul(input_clamped, input_clamped);
+ llvm::Value* numerator =
+ llvm::ConstantFP::get(vector_type, numerator_coeffs[0]);
+ for (int i = 1; i < numerator_coeffs.size(); i++) {
+ numerator = ir_builder.CreateFAdd(
+ ir_builder.CreateFMul(input_squared, numerator),
+ llvm::ConstantFP::get(vector_type, numerator_coeffs[i]));
+ }
+ numerator = ir_builder.CreateFMul(input_clamped, numerator);
+
+ llvm::Value* denominator =
+ llvm::ConstantFP::get(vector_type, denominator_coeffs[0]);
+ for (int i = 1; i < denominator_coeffs.size(); i++) {
+ denominator = ir_builder.CreateFAdd(
+ ir_builder.CreateFMul(input_squared, denominator),
+ llvm::ConstantFP::get(vector_type, denominator_coeffs[i]));
+ }
+
+ llvm::Value* result = ir_builder.CreateFDiv(numerator, denominator);
+ ir_builder.CreateRet(result);
+
+ DCHECK(!llvm::verifyFunction(*vector_tanh_function));
+ return vector_tanh_function;
+}
+} // namespace
+
+void RewriteIRRuntimeFunctions(llvm::Module* module) {
+ auto* tanh_v4f32 = EmitVectorF32TanhIfNeeded(module, kTanhV4F32SymbolName,
+ /*vector_width=*/4);
+ auto* tanh_v8f32 = EmitVectorF32TanhIfNeeded(module, kTanhV8F32SymbolName,
+ /*vector_width=*/8);
+
+ // Gather all the call sites, force inline them and then delete the vector
+ // function bodies.
+
+ std::vector<llvm::CallInst*> calls_to_inline;
+ for (auto* function : {tanh_v4f32, tanh_v8f32}) {
+ if (function != nullptr) {
+ for (auto* user : function->users()) {
+ calls_to_inline.push_back(llvm::cast<llvm::CallInst>(user));
+ }
+ }
+ }
+
+ for (auto* call_to_inline : calls_to_inline) {
+ llvm::InlineFunctionInfo inline_function_info;
+ CHECK(llvm::InlineFunction(call_to_inline, inline_function_info));
+ }
+
+ for (auto* function : {tanh_v4f32, tanh_v8f32}) {
+ if (function != nullptr) {
+ function->eraseFromParent();
+ }
+ }
+}
+
+} // namespace runtime
+} // namespace cpu
+} // namespace xla
diff --git a/tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.h b/tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.h
new file mode 100644
index 0000000000..4a0c9d8946
--- /dev/null
+++ b/tensorflow/compiler/xla/service/cpu/llvm_ir_runtime.h
@@ -0,0 +1,42 @@
+/* Copyright 2017 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.
+==============================================================================*/
+
+#ifndef TENSORFLOW_COMPILER_XLA_SERVICE_CPU_LLVM_IR_RUNTINE_H_
+#define TENSORFLOW_COMPILER_XLA_SERVICE_CPU_LLVM_IR_RUNTINE_H_
+
+#include "llvm/IR/Module.h"
+
+namespace xla {
+namespace cpu {
+namespace runtime {
+
+extern const char* const kTanhV4F32SymbolName;
+extern const char* const kTanhV8F32SymbolName;
+
+// The following CPU runtime functions have LLVM-IR only implementations:
+//
+// - __xla_cpu_runtime_TanhV4F32
+// - __xla_cpu_runtime_TanhV8F32
+//
+// |LinkIRRuntimeFunctions| rewrites calls to these functions into generic LLVM
+// IR.
+
+void RewriteIRRuntimeFunctions(llvm::Module* module);
+
+} // namespace runtime
+} // namespace cpu
+} // namespace xla
+
+#endif // TENSORFLOW_COMPILER_XLA_SERVICE_CPU_LLVM_IR_RUNTINE_H_
diff --git a/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc b/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc
index b46ac67096..9eb714ed87 100644
--- a/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc
+++ b/tensorflow/compiler/xla/service/cpu/simple_orc_jit.cc
@@ -93,10 +93,8 @@ class JITSymbolTable {
ADD_JIT_SYMBOL_TO_TABLE(ReleaseOutfeedBufferAfterPopulation);
ADD_JIT_SYMBOL_TO_TABLE(ExpV8F32);
ADD_JIT_SYMBOL_TO_TABLE(LogV8F32);
- ADD_JIT_SYMBOL_TO_TABLE(TanhV8F32);
ADD_JIT_SYMBOL_TO_TABLE(ExpV4F32);
ADD_JIT_SYMBOL_TO_TABLE(LogV4F32);
- ADD_JIT_SYMBOL_TO_TABLE(TanhV4F32);
ADD_JIT_SYMBOL_TO_TABLE(EigenConvF32);
ADD_JIT_SYMBOL_TO_TABLE(EigenMatMulF32);
ADD_JIT_SYMBOL_TO_TABLE(EigenMatMulF64);
diff --git a/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc b/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc
index 821418afd0..7dba4e52f0 100644
--- a/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc
+++ b/tensorflow/compiler/xla/tests/array_elementwise_ops_test.cc
@@ -1559,6 +1559,50 @@ TEST_F(ArrayElementwiseOpTest, TanhF32s) {
error_spec_);
}
+TEST_F(ArrayElementwiseOpTest, TanhF32sVector) {
+ // This is like the test ArrayElementwiseOpTest.TanhF32s above, except that
+ // the input tensor is large enough to exercise the vectorized tanh
+ // implementation.
+ ComputationBuilder builder(client_, TestName());
+ auto input_literal = Literal::CreateR2<float>(
+ {{1.02, -0.32, 0.85, 0.90, 1.23, -0.91, -0.49, 0.80},
+ {-0.67, 0.16, -0.07, 0.39, -0.41, 0.04, 1.36, 1.25},
+ {0.41, 0.65, -1.08, 0.32, -1.45, -0.77, -1.09, 0.91},
+ {-1.03, -0.30, -1.11, -1.17, 1.50, -0.85, 0.04, 1.02},
+ {0.34, -0.61, 0.41, 0.07, -0.02, 1.42, -0.62, 0.81},
+ {0.08, 0.81, -0.30, 1.17, -0.65, -0.44, 0.92, 1.26},
+ {-1.29, 1.35, 0.08, -1.24, -0.92, 0.49, 1.17, -0.45},
+ {-1.31, -1.44, -0.13, -1.31, -0.79, 1.41, 1.21, 1.05}});
+ auto input_data =
+ client_->TransferToServer(*input_literal).ConsumeValueOrDie();
+
+ auto input = builder.Parameter(0, input_literal->shape(), "input");
+ builder.Tanh(input);
+
+ ComputeAndCompareR2<float>(
+ &builder,
+ {{0.77009583, -0.30665702, 0.69070244, 0.71401149, 0.84400684,
+ -0.71985596, -0.45764771, 0.66664988},
+ {-0.58278900, 0.16050975, -0.06770509, 0.36843640, -0.38476998,
+ 0.04018109, 0.87562293, 0.84788644},
+ {0.38603750, 0.57294142, -0.79140943, 0.31032649, -0.89590985,
+ -0.64770776, -0.79625875, 0.72234446},
+ {-0.77389336, -0.28871772, -0.80428445, -0.82541436, 0.90456349,
+ -0.68856895, 0.03877772, 0.76877952},
+ {0.32561871, -0.54546672, 0.39072621, 0.07273290, -0.01924866,
+ 0.88924897, -0.55283129, 0.67183107},
+ {0.08006320, 0.66944766, -0.29068485, 0.82573754, -0.57170743,
+ -0.41581789, 0.72739530, 0.85025692},
+ {-0.85931867, 0.87357593, 0.07782833, -0.84597743, -0.72748238,
+ 0.45396307, 0.82449573, -0.42462519},
+ {-0.86363792, -0.89368379, -0.12621804, -0.86445558, -0.65565848,
+ 0.88789743, 0.83566397, 0.78287679}},
+ {input_data.get()},
+ // The error spec is unusually high here to account for the fact that we
+ // use a rational interpolant to approximate tanh.
+ ErrorSpec(0.004, 0.004));
+}
+
TEST_F(ArrayElementwiseOpTest, AddChainFoldLeft) {
// a ------ (add) --------- (add)
// / /
diff --git a/tensorflow/core/ops/ops.pbtxt b/tensorflow/core/ops/ops.pbtxt
index 1f947092d1..8678929497 100644
--- a/tensorflow/core/ops/ops.pbtxt
+++ b/tensorflow/core/ops/ops.pbtxt
@@ -12170,7 +12170,7 @@ op {
}
}
}
- summary: "Computes the determinant of one ore more square matrices."
+ summary: "Computes the determinant of one or more square matrices."
description: "The input is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions\nform square matrices. The output is a tensor containing the determinants\nfor all input submatrices `[..., :, :]`."
}
op {
diff --git a/tensorflow/docs_src/deploy/index.md b/tensorflow/docs_src/deploy/index.md
index 644115b8ff..b935ebd637 100644
--- a/tensorflow/docs_src/deploy/index.md
+++ b/tensorflow/docs_src/deploy/index.md
@@ -5,11 +5,6 @@ the following documents:
* @{$distributed$Distributed TensorFlow}, which explains how to create
a cluster of TensorFlow servers.
- * @{$tfserve$TensorFlow Serving}, which describes TensorFlow Serving--an
- open-source serving system for machine learning models. This document
- provides a short introduction to TensorFlow Serving; the bulk of the
- documentation about TensorFlow Serving is in a
- [separate website](https://tensorflow.github.io/serving/serving_basic).
* @{$hadoop$How to run TensorFlow on Hadoop}, which has a highly
self-explanatory title.
diff --git a/tensorflow/docs_src/deploy/leftnav_files b/tensorflow/docs_src/deploy/leftnav_files
index 6f5821cfd5..f8f8d578e6 100644
--- a/tensorflow/docs_src/deploy/leftnav_files
+++ b/tensorflow/docs_src/deploy/leftnav_files
@@ -1,4 +1,3 @@
index.md
distributed.md
-tfserve.md
hadoop.md
diff --git a/tensorflow/docs_src/deploy/tfserve.md b/tensorflow/docs_src/deploy/tfserve.md
deleted file mode 100644
index 8b11b6ad2a..0000000000
--- a/tensorflow/docs_src/deploy/tfserve.md
+++ /dev/null
@@ -1,30 +0,0 @@
-# TensorFlow Serving
-
-## Introduction
-
-TensorFlow Serving is a flexible, high-performance serving system for machine
-learning models, designed for production environments. TensorFlow Serving
-makes it easy to deploy new algorithms and experiments, while keeping the same
-server architecture and APIs.
-
-## Basic Serving Tutorial
-
-See the [basic tutorial](https://tensorflow.github.io/serving/serving_basic)
-on the TensorFlow Serving site to learn how to export a trained TensorFlow
-model and build a server to serve the exported model.
-
-## Advanced Serving Tutorial
-
-See the
-[advanced tutorial](https://tensorflow.github.io/serving/serving_advanced)
-on the TensorFlow Serving site to learn how to build a server that
-dynamically discovers and serves new versions of a trained TensorFlow
-model.
-
-## Serving Inception Model Tutorial
-
-See the
-[serving inception tutorial](https://tensorflow.github.io/serving/serving_inception)
-on the TensorFlow Serving site to learn how to serve the inception model with
-TensorFlow Serving and Kubernetes.
-
diff --git a/tensorflow/docs_src/programmers_guide/leftnav_files b/tensorflow/docs_src/programmers_guide/leftnav_files
index 7f0b9b8db9..2a58c4647d 100644
--- a/tensorflow/docs_src/programmers_guide/leftnav_files
+++ b/tensorflow/docs_src/programmers_guide/leftnav_files
@@ -9,7 +9,7 @@ reading_data.md
embedding.md
debugger.md
supervisor.md
-saved_model_cli.md
+saved_model.md
meta_graph.md
version_compat.md
faq.md
diff --git a/tensorflow/docs_src/programmers_guide/saved_model.md b/tensorflow/docs_src/programmers_guide/saved_model.md
index e169efe19c..9262143ad8 100644
--- a/tensorflow/docs_src/programmers_guide/saved_model.md
+++ b/tensorflow/docs_src/programmers_guide/saved_model.md
@@ -440,10 +440,10 @@ does not specify one.
### Serving the exported model locally
For local deployment, you can serve your model using
-@{$deploy/tfserve$Tensorflow Serving}, an open-source project that loads a
+[TensorFlow Serving](http://github.com/tensorflow/serving), an open-source project that loads a
SavedModel and exposes it as a [gRPC](http://www.grpc.io/) service.
-First, [install TensorFlow Serving](https://tensorflow.github.io/serving/setup#prerequisites).
+First, [install TensorFlow Serving](http://github.com/tensorflow/serving).
Then build and run the local model server, substituting `$export_dir_base` with
the path to the SavedModel you exported above:
diff --git a/tensorflow/go/op/wrappers.go b/tensorflow/go/op/wrappers.go
index b6d8b0db67..1ae27298ec 100644
--- a/tensorflow/go/op/wrappers.go
+++ b/tensorflow/go/op/wrappers.go
@@ -21772,7 +21772,7 @@ func Sin(scope *Scope, x tf.Output) (y tf.Output) {
return op.Output(0)
}
-// Computes the determinant of one ore more square matrices.
+// Computes the determinant of one or more square matrices.
//
// The input is a tensor of shape `[..., M, M]` whose inner-most 2 dimensions
// form square matrices. The output is a tensor containing the determinants
diff --git a/tensorflow/java/maven/run_inside_container.sh b/tensorflow/java/maven/run_inside_container.sh
index 302ed96c12..6b4d5d7032 100644
--- a/tensorflow/java/maven/run_inside_container.sh
+++ b/tensorflow/java/maven/run_inside_container.sh
@@ -32,7 +32,7 @@ clean() {
# (though if run inside a clean docker container, there won't be any dirty
# artifacts lying around)
mvn -q clean
- rm -rf libtensorflow_jni/src libtensorflow_jni/target libtensorflow/src libtensorflow/target
+ rm -rf libtensorflow_jni/src libtensorflow_jni/target libtensorflow/src libtensorflow/target tensorflow-android/target
}
update_version_in_pom() {
@@ -52,6 +52,17 @@ download_libtensorflow() {
cd "${DIR}"
}
+# Fetch the android aar artifact from the CI build system, and update
+# its associated pom file.
+update_tensorflow_android() {
+ TARGET_DIR="${DIR}/tensorflow-android/target"
+ mkdir -p "${TARGET_DIR}"
+ python "${DIR}/tensorflow-android/update.py" \
+ --version "${TF_VERSION}" \
+ --template "${DIR}/tensorflow-android/pom-android.xml.template" \
+ --dir "${TARGET_DIR}"
+}
+
download_libtensorflow_jni() {
NATIVE_DIR="${DIR}/libtensorflow_jni/src/main/resources/org/tensorflow/native"
mkdir -p "${NATIVE_DIR}"
@@ -126,6 +137,29 @@ generate_java_protos() {
rm -rf "${DIR}/proto/tmp"
}
+# If successfully built, try to deploy.
+# If successfully deployed, clean.
+# If deployment fails, debug with
+# ./release.sh ${TF_VERSION} ${SETTINGS_XML} bash
+# To get a shell to poke around the maven artifacts with.
+deploy_artifacts() {
+ # This deploys the non-android pieces
+ mvn deploy
+
+ # Sign and deploy the previously downloaded aar file as a single
+ # maven artifact.
+ if [[ "${IS_SNAPSHOT}" == "true" ]]; then
+ REPO="https://oss.sonatype.org/content/repositories/snapshots"
+ else
+ REPO="https://oss.sonatype.org/service/local/staging/deploy/maven2/"
+ fi
+ mvn gpg:sign-and-deploy-file -Dfile="${DIR}/tensorflow-android/target/tensorflow.aar" -DpomFile="${DIR}/tensorflow-android/target/pom-android.xml" -Durl=${REPO} -DrepositoryId=ossrh
+
+ # Clean up when everything works
+ clean
+}
+
+
if [ -z "${TF_VERSION}" ]
then
echo "Must set the TF_VERSION environment variable"
@@ -144,15 +178,12 @@ clean
update_version_in_pom
download_libtensorflow
download_libtensorflow_jni
+update_tensorflow_android
generate_java_protos
# Build the release artifacts
mvn verify
-# If successfully built, try to deploy.
-# If successfully deployed, clean.
-# If deployment fails, debug with
-# ./release.sh ${TF_VERSION} ${SETTINGS_XML} bash
-# To get a shell to poke around the maven artifacts with.
-mvn deploy && clean
+# Push artifacts to repository
+deploy_artifacts
set +ex
if [[ "${IS_SNAPSHOT}" == "false" ]]; then
diff --git a/tensorflow/java/maven/tensorflow-android/pom-android.xml.template b/tensorflow/java/maven/tensorflow-android/pom-android.xml.template
new file mode 100644
index 0000000000..5cbd0c898d
--- /dev/null
+++ b/tensorflow/java/maven/tensorflow-android/pom-android.xml.template
@@ -0,0 +1,29 @@
+<project
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.tensorflow</groupId>
+ <artifactId>tensorflow-android</artifactId>
+ <version>${version}</version>
+ <packaging>aar</packaging>
+
+ <name>TensorFlow AAR for Android Inference Library and Java API</name>
+ <url>https://github.com/tensorflow/tensorflow/</url>
+ <parent>
+ <groupId>org.tensorflow</groupId>
+ <artifactId>parentpom</artifactId>
+ <version>${version}</version>
+ <relativePath>../</relativePath>
+ </parent>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.build.number>${build_number}</project.build.number>
+ <project.build.commitid>${build_commit_id}</project.build.commitid>
+ <project.build.type>${build_type}</project.build.type>
+ <project.build.url>${build_url}</project.build.url>
+ </properties>
+
+</project>
diff --git a/tensorflow/java/maven/tensorflow-android/update.py b/tensorflow/java/maven/tensorflow-android/update.py
new file mode 100644
index 0000000000..bd97a08948
--- /dev/null
+++ b/tensorflow/java/maven/tensorflow-android/update.py
@@ -0,0 +1,139 @@
+# Copyright 2017 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.
+"""Fetch android artifacts and update pom properties."""
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import argparse
+import json
+import string
+import sys
+import urllib2
+
+
+def get_args():
+ """Parse command line args."""
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ '--version', required=True, help='Version for the artifact.')
+ parser.add_argument(
+ '--dir',
+ required=True,
+ help='Directory where the pom and aar artifact will be written.')
+ parser.add_argument(
+ '--template', required=True, help='Path to pom template file.')
+ return parser.parse_args()
+
+
+def get_json(url):
+ """Load the contents of the URL as a json object."""
+ return json.load(urllib2.urlopen(url))
+
+
+def get_commit_id(build_info):
+ """Fetch the git commit id from the build info json object."""
+ actions = build_info.get('actions')
+ build_data = next(
+ a for a in actions
+ if a.get('_class') == 'hudson.plugins.git.util.BuildData')
+ if not build_data:
+ raise ValueError('Missing BuildData: %s' % build_info)
+ revision_info = build_data.get('lastBuiltRevision')
+ if not revision_info:
+ raise ValueError('Missing lastBuiltRevision: %s' % build_info)
+ return revision_info.get('SHA1')
+
+
+def get_aar_url(build_info):
+ """Given the json build info, find the URL to the tensorflow.aar artifact."""
+ base_url = build_info.get('url')
+ if not base_url:
+ raise ValueError('Missing url: %s' % build_info)
+ build_class = build_info.get('_class')
+ if (build_class == 'hudson.model.FreeStyleBuild' or
+ build_class == 'hudson.matrix.MatrixRun'):
+ aar_info = next(
+ a for a in build_info.get('artifacts')
+ if a.get('fileName') == 'tensorflow.aar')
+ if not aar_info:
+ raise ValueError('Missing aar artifact: %s' % build_info)
+ return '%s/artifact/%s' % (base_url, aar_info.get('relativePath'))
+
+ raise ValueError('Unknown build_type %s' % build_info)
+
+
+def read_template(path):
+ with open(path) as f:
+ return string.Template(f.read())
+
+
+def main():
+ args = get_args()
+
+ # Artifacts are downloaded from the ci build. A SNAPSHOT release is
+ # associated with artifacts from the last successful nightly build. Otherwise,
+ # it comes from the officially blessed release artifacts.
+ if args.version.endswith('SNAPSHOT'):
+ info_url = ('https://ci.tensorflow.org/view/Nightly/job/nightly-android'
+ '/lastSuccessfulBuild/api/json')
+ aar_url = None
+ build_type = 'nightly-android'
+ else:
+ release_prefix = 'https://storage.googleapis.com/tensorflow/libtensorflow'
+ info_url = '/%s/android_buildinfo-%s.json' % (release_prefix, args.version)
+ aar_url = '/%s/tensorflow-%s.aar' % (release_prefix, args.version)
+ build_type = 'release-matrix-android'
+
+ # Retrieve build information
+ build_info = get_json(info_url)
+
+ # Check all required build info is present
+ if build_info.get('result') != 'SUCCESS':
+ raise ValueError('Invalid json: %s' % build_info)
+ build_url = build_info.get('url')
+ if not build_url:
+ raise ValueError('Missing url: %s' % build_info)
+ build_number = build_info.get('number')
+ if not build_number:
+ raise ValueError('Missing build number: %s' % build_info)
+ build_commit_id = get_commit_id(build_info)
+ if not build_commit_id:
+ raise ValueError('Missing commit id: %s' % build_info)
+
+ # Write the pom file updated with build attributes.
+ template = read_template(args.template)
+ with open('%s/pom-android.xml' % args.dir, 'w') as f:
+ f.write(
+ template.substitute({
+ 'build_commit_id': build_commit_id,
+ 'build_number': build_number,
+ 'build_type': build_type,
+ 'build_url': build_url,
+ 'version': args.version
+ }))
+
+ # Retrieve the aar location if needed.
+ if not aar_url:
+ aar_url = get_aar_url(build_info)
+
+ # And download the aar to the desired location.
+ with open('%s/tensorflow.aar' % args.dir, 'w') as f:
+ aar = urllib2.urlopen(aar_url)
+ f.write(aar.read())
+
+
+if __name__ == '__main__':
+ sys.exit(main())