Modifications per recommended changes.
* Document Scope as not offering thread-safety * Remove synchronized sections within Scope * Restrict withName() and withSubScope() to only allow names matching [A-Za-z0-9.][A-Za-z0-9_.\\-]* * Consolidate tensorflow and tensorflow_op into one BUILD target * Fix mistake in opname in Javadoc example * Change method qualifier in inner test classes to default * rename baseName -> opPrefix, baseOpName -> opName
This commit is contained in:
parent
3072c2f239
commit
950a38564d
@ -9,22 +9,15 @@ load("build_defs", "JAVACOPTS")
|
|||||||
|
|
||||||
java_library(
|
java_library(
|
||||||
name = "tensorflow",
|
name = "tensorflow",
|
||||||
srcs = [":java_sources"],
|
srcs = [
|
||||||
|
":java_op_sources",
|
||||||
|
":java_sources",
|
||||||
|
],
|
||||||
data = [":libtensorflow_jni"],
|
data = [":libtensorflow_jni"],
|
||||||
javacopts = JAVACOPTS,
|
javacopts = JAVACOPTS,
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
# Operator convenience wrappers for the core tensorflow library.
|
|
||||||
java_library(
|
|
||||||
name = "tensorflow_op",
|
|
||||||
srcs = [
|
|
||||||
":java_op_sources",
|
|
||||||
],
|
|
||||||
javacopts = JAVACOPTS,
|
|
||||||
deps = [":tensorflow"],
|
|
||||||
)
|
|
||||||
|
|
||||||
# NOTE(ashankar): Rule to include the Java API in the Android Inference Library
|
# NOTE(ashankar): Rule to include the Java API in the Android Inference Library
|
||||||
# .aar. At some point, might make sense for a .aar rule here instead.
|
# .aar. At some point, might make sense for a .aar rule here instead.
|
||||||
filegroup(
|
filegroup(
|
||||||
@ -164,7 +157,6 @@ java_test(
|
|||||||
test_class = "org.tensorflow.op.ScopeTest",
|
test_class = "org.tensorflow.op.ScopeTest",
|
||||||
deps = [
|
deps = [
|
||||||
":tensorflow",
|
":tensorflow",
|
||||||
":tensorflow_op",
|
|
||||||
":testutil",
|
":testutil",
|
||||||
"@junit",
|
"@junit",
|
||||||
],
|
],
|
||||||
|
@ -32,41 +32,34 @@ import java.util.regex.Pattern;
|
|||||||
* <p>This class is package private, user code creates {@link Scope} which internally delegates
|
* <p>This class is package private, user code creates {@link Scope} which internally delegates
|
||||||
* calls to an underlying {@code NameScope}.
|
* calls to an underlying {@code NameScope}.
|
||||||
*
|
*
|
||||||
* <p>This class is thread-safe.
|
* <p>This class is <b>not</b> thread-safe.
|
||||||
*/
|
*/
|
||||||
final class NameScope {
|
final class NameScope {
|
||||||
|
|
||||||
NameScope withSubScope(String scopeName) {
|
NameScope withSubScope(String scopeName) {
|
||||||
if (baseName == null) {
|
checkPattern(NAME_REGEX, scopeName);
|
||||||
checkPattern(OP_NAME_REGEX, scopeName);
|
|
||||||
} else {
|
|
||||||
checkPattern(SUBSCOPE_NAME_REGEX, scopeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (baseOpName != null) {
|
// Override with opName if it exists.
|
||||||
// Use the base name instead to derive the subscope.
|
String actualName = (opName != null) ? opName : scopeName;
|
||||||
scopeName = baseOpName;
|
|
||||||
}
|
|
||||||
|
|
||||||
String newBaseName = fullyQualify(makeUnique(scopeName));
|
String newPrefix = fullyQualify(makeUnique(actualName));
|
||||||
return new NameScope(newBaseName, null, null);
|
return new NameScope(newPrefix, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
NameScope withName(String name) {
|
NameScope withName(String name) {
|
||||||
checkPattern(OP_NAME_REGEX, name);
|
checkPattern(NAME_REGEX, name);
|
||||||
|
|
||||||
// All context except for the baseOpName is shared with the new scope.
|
// All context except for the opName is shared with the new scope.
|
||||||
return new NameScope(baseName, name, ids);
|
return new NameScope(opPrefix, name, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
String makeOpName(String opName) {
|
String makeOpName(String name) {
|
||||||
checkPattern(OP_NAME_REGEX, opName);
|
checkPattern(NAME_REGEX, name);
|
||||||
|
|
||||||
if (baseOpName != null) {
|
// Override with opName if it exists.
|
||||||
opName = baseOpName;
|
String actualName = (opName != null) ? opName : name;
|
||||||
}
|
|
||||||
opName = makeUnique(opName);
|
return fullyQualify(makeUnique(actualName));
|
||||||
return fullyQualify(opName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,9 +72,9 @@ final class NameScope {
|
|||||||
this(null, null, null);
|
this(null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NameScope(String baseName, String baseOpName, Map<String, Integer> ids) {
|
private NameScope(String opPrefix, String opName, Map<String, Integer> ids) {
|
||||||
this.baseName = baseName;
|
this.opPrefix = opPrefix;
|
||||||
this.baseOpName = baseOpName;
|
this.opName = opName;
|
||||||
if (ids != null) {
|
if (ids != null) {
|
||||||
this.ids = ids;
|
this.ids = ids;
|
||||||
} else {
|
} else {
|
||||||
@ -101,7 +94,6 @@ final class NameScope {
|
|||||||
// The second use of makeUnique("a") updates ids to "a" -> 2
|
// The second use of makeUnique("a") updates ids to "a" -> 2
|
||||||
// and returns "a_1", and so on.
|
// and returns "a_1", and so on.
|
||||||
private String makeUnique(String id) {
|
private String makeUnique(String id) {
|
||||||
synchronized (ids) {
|
|
||||||
if (!ids.containsKey(id)) {
|
if (!ids.containsKey(id)) {
|
||||||
ids.put(id, 1);
|
ids.put(id, 1);
|
||||||
return id;
|
return id;
|
||||||
@ -111,23 +103,22 @@ final class NameScope {
|
|||||||
return String.format("%s_%d", id, cur);
|
return String.format("%s_%d", id, cur);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private String fullyQualify(String name) {
|
private String fullyQualify(String name) {
|
||||||
if (baseName != null) {
|
if (opPrefix != null) {
|
||||||
return String.format("%s/%s", baseName, name);
|
return String.format("%s/%s", opPrefix, name);
|
||||||
} else {
|
} else {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If baseName is non-null, it is a prefix applied to all names
|
// If opPrefix is non-null, it is a prefix applied to all names
|
||||||
// created by this instance.
|
// created by this instance.
|
||||||
private final String baseName;
|
private final String opPrefix;
|
||||||
|
|
||||||
// If baseOpName is non-null, it is used to derive the unique name
|
// If opName is non-null, it is used to derive the unique name
|
||||||
// for operators rather than the provided default name.
|
// for operators rather than the provided default name.
|
||||||
private final String baseOpName;
|
private final String opName;
|
||||||
|
|
||||||
// NameScope generates unique names by appending a numeric suffix if
|
// NameScope generates unique names by appending a numeric suffix if
|
||||||
// needed. This is a map containing names already created by this
|
// needed. This is a map containing names already created by this
|
||||||
@ -153,6 +144,5 @@ final class NameScope {
|
|||||||
// LETTER_DIGIT_DOT, followed by zero or more LETTER_DIGIT_DASH_DOT_SLASH_UNDERSCORE. SLASH is not
|
// LETTER_DIGIT_DOT, followed by zero or more LETTER_DIGIT_DASH_DOT_SLASH_UNDERSCORE. SLASH is not
|
||||||
// permitted in actual user-supplied names to NameScope - it is used as a reserved character to
|
// permitted in actual user-supplied names to NameScope - it is used as a reserved character to
|
||||||
// separate subcomponents within fully qualified names.
|
// separate subcomponents within fully qualified names.
|
||||||
private static final Pattern OP_NAME_REGEX = Pattern.compile("[A-Za-z0-9.][A-Za-z0-9_.\\-]*");
|
private static final Pattern NAME_REGEX = Pattern.compile("[A-Za-z0-9.][A-Za-z0-9_.\\-]*");
|
||||||
private static final Pattern SUBSCOPE_NAME_REGEX = Pattern.compile("[A-Za-z0-9_.\\-]+");
|
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ import org.tensorflow.Graph;
|
|||||||
* public class Constant {
|
* public class Constant {
|
||||||
* public static Constant create(Scope scope, ...) {
|
* public static Constant create(Scope scope, ...) {
|
||||||
* scope.graph().opBuilder(
|
* scope.graph().opBuilder(
|
||||||
* "Constant", scope.makeOpName("Constant"))
|
* "Const", scope.makeOpName("Const"))
|
||||||
* .setAttr(...)
|
* .setAttr(...)
|
||||||
* .build()
|
* .build()
|
||||||
* ...
|
* ...
|
||||||
@ -61,17 +61,17 @@ import org.tensorflow.Graph;
|
|||||||
* // This op name will be "linear/W"
|
* // This op name will be "linear/W"
|
||||||
* Constant.create(linear.withName("W"), ...);
|
* Constant.create(linear.withName("W"), ...);
|
||||||
*
|
*
|
||||||
* // This op will be "linear/Constant", using the default
|
* // This op will be "linear/Const", using the default
|
||||||
* // name provided by Constant
|
* // name provided by Constant
|
||||||
* Constant.create(linear, ...);
|
* Constant.create(linear, ...);
|
||||||
*
|
*
|
||||||
* // This op will be "linear/Constant_1", using the default
|
* // This op will be "linear/Const_1", using the default
|
||||||
* // name provided by Constant and making it unique within
|
* // name provided by Constant and making it unique within
|
||||||
* // this scope
|
* // this scope
|
||||||
* Constant.create(linear, ...);
|
* Constant.create(linear, ...);
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* <p>Scope objects are thread-safe.
|
* <p>Scope objects are <b>not</b> thread-safe.
|
||||||
*/
|
*/
|
||||||
public final class Scope {
|
public final class Scope {
|
||||||
|
|
||||||
@ -96,12 +96,7 @@ public final class Scope {
|
|||||||
* name will be unique in the returned scope. All other properties are inherited from the current
|
* name will be unique in the returned scope. All other properties are inherited from the current
|
||||||
* scope.
|
* scope.
|
||||||
*
|
*
|
||||||
* <p>Valid child scope names must match one of the following regular expressions:
|
* <p>The child scope name must match the regular expression {@code [A-Za-z0-9.][A-Za-z0-9_.\-]*}
|
||||||
*
|
|
||||||
* <pre>{@code
|
|
||||||
* [A-Za-z0-9.][A-Za-z0-9_.\\-]* (for scopes at the root)
|
|
||||||
* [A-Za-z0-9_.\\-]+ (for other scopes)
|
|
||||||
* }</pre>
|
|
||||||
*
|
*
|
||||||
* @param childScopeName name for the new child scope
|
* @param childScopeName name for the new child scope
|
||||||
* @return a new subscope
|
* @return a new subscope
|
||||||
@ -117,7 +112,7 @@ public final class Scope {
|
|||||||
* <p>Operations created within this scope will have a name of the form {@code
|
* <p>Operations created within this scope will have a name of the form {@code
|
||||||
* name/opName[_suffix]}. This lets you name a specific operator more meaningfully.
|
* name/opName[_suffix]}. This lets you name a specific operator more meaningfully.
|
||||||
*
|
*
|
||||||
* <p>Valid operator names must match the regular expression {@code [A-Za-z0-9.][A-Za-z0-9_.\\-]*}
|
* <p>Names must match the regular expression {@code [A-Za-z0-9.][A-Za-z0-9_.\-]*}
|
||||||
*
|
*
|
||||||
* @param opName name for an operator in the returned scope
|
* @param opName name for an operator in the returned scope
|
||||||
* @return a new Scope that uses opName for operations.
|
* @return a new Scope that uses opName for operations.
|
||||||
@ -136,7 +131,7 @@ public final class Scope {
|
|||||||
* instance. Typical operator building code might look like
|
* instance. Typical operator building code might look like
|
||||||
*
|
*
|
||||||
* <pre>{@code
|
* <pre>{@code
|
||||||
* scope.graph().opBuilder("Constant", scope.makeOpName("Constant"))...
|
* scope.graph().opBuilder("Const", scope.makeOpName("Const"))...
|
||||||
* }</pre>
|
* }</pre>
|
||||||
*
|
*
|
||||||
* <p><b>Note:</b> if you provide a composite operator building class (i.e, a class that adds a
|
* <p><b>Note:</b> if you provide a composite operator building class (i.e, a class that adds a
|
||||||
|
@ -87,7 +87,7 @@ public class ScopeTest {
|
|||||||
Scope root = new Scope(g);
|
Scope root = new Scope(g);
|
||||||
|
|
||||||
final String[] invalid_names = {
|
final String[] invalid_names = {
|
||||||
"_", // Names are constrained to start with [A-Za-z0-9.]
|
"_", "-", "-x", // Names are constrained to start with [A-Za-z0-9.]
|
||||||
null, "", "a$", // Invalid characters
|
null, "", "a$", // Invalid characters
|
||||||
"a/b", // slashes not allowed
|
"a/b", // slashes not allowed
|
||||||
};
|
};
|
||||||
@ -99,7 +99,7 @@ public class ScopeTest {
|
|||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
// expected
|
// expected
|
||||||
}
|
}
|
||||||
// Root scopes follow the same rules as opnames
|
// Subscopes follow the same rules
|
||||||
try {
|
try {
|
||||||
root.withSubScope(name);
|
root.withSubScope(name);
|
||||||
fail("failed to catch invalid scope name: " + name);
|
fail("failed to catch invalid scope name: " + name);
|
||||||
@ -108,8 +108,13 @@ public class ScopeTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-root scopes have a less restrictive constraint.
|
// Unusual but valid names.
|
||||||
assertEquals("a/_/hello", root.withSubScope("a").withSubScope("_").makeOpName("hello"));
|
final String[] valid_names = {".", "..", "._-.", "a--."};
|
||||||
|
|
||||||
|
for (String name : valid_names) {
|
||||||
|
root.withName(name);
|
||||||
|
root.withSubScope(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,7 +180,7 @@ public class ScopeTest {
|
|||||||
private static final class Const {
|
private static final class Const {
|
||||||
private final Output output;
|
private final Output output;
|
||||||
|
|
||||||
private static Const create(Scope s, Object v) {
|
static Const create(Scope s, Object v) {
|
||||||
try (Tensor value = Tensor.create(v)) {
|
try (Tensor value = Tensor.create(v)) {
|
||||||
return new Const(
|
return new Const(
|
||||||
s.graph()
|
s.graph()
|
||||||
@ -187,11 +192,11 @@ public class ScopeTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Const(Output o) {
|
Const(Output o) {
|
||||||
output = o;
|
output = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Output output() {
|
Output output() {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +204,7 @@ public class ScopeTest {
|
|||||||
private static final class Mean {
|
private static final class Mean {
|
||||||
private final Output output;
|
private final Output output;
|
||||||
|
|
||||||
private static Mean create(Scope s, Output input, Output reductionIndices) {
|
static Mean create(Scope s, Output input, Output reductionIndices) {
|
||||||
return new Mean(
|
return new Mean(
|
||||||
s.graph()
|
s.graph()
|
||||||
.opBuilder("Mean", s.makeOpName("Mean"))
|
.opBuilder("Mean", s.makeOpName("Mean"))
|
||||||
@ -209,11 +214,11 @@ public class ScopeTest {
|
|||||||
.output(0));
|
.output(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mean(Output o) {
|
Mean(Output o) {
|
||||||
output = o;
|
output = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Output output() {
|
Output output() {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,7 +226,7 @@ public class ScopeTest {
|
|||||||
private static final class SquaredDifference {
|
private static final class SquaredDifference {
|
||||||
private final Output output;
|
private final Output output;
|
||||||
|
|
||||||
private static SquaredDifference create(Scope s, Output x, Output y) {
|
static SquaredDifference create(Scope s, Output x, Output y) {
|
||||||
return new SquaredDifference(
|
return new SquaredDifference(
|
||||||
s.graph()
|
s.graph()
|
||||||
.opBuilder("SquaredDifference", s.makeOpName("SquaredDifference"))
|
.opBuilder("SquaredDifference", s.makeOpName("SquaredDifference"))
|
||||||
@ -231,11 +236,11 @@ public class ScopeTest {
|
|||||||
.output(0));
|
.output(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private SquaredDifference(Output o) {
|
SquaredDifference(Output o) {
|
||||||
output = o;
|
output = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Output output() {
|
Output output() {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,7 +248,7 @@ public class ScopeTest {
|
|||||||
private static final class Variance {
|
private static final class Variance {
|
||||||
private final Output output;
|
private final Output output;
|
||||||
|
|
||||||
private static Variance create(Scope base, Output x) {
|
static Variance create(Scope base, Output x) {
|
||||||
Scope s = base.withSubScope("variance");
|
Scope s = base.withSubScope("variance");
|
||||||
Output zero = Const.create(s.withName("zero"), new int[] {0}).output();
|
Output zero = Const.create(s.withName("zero"), new int[] {0}).output();
|
||||||
Output sqdiff =
|
Output sqdiff =
|
||||||
@ -254,11 +259,11 @@ public class ScopeTest {
|
|||||||
return new Variance(Mean.create(s.withName("variance"), sqdiff, zero).output());
|
return new Variance(Mean.create(s.withName("variance"), sqdiff, zero).output());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variance(Output o) {
|
Variance(Output o) {
|
||||||
output = o;
|
output = o;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Output output() {
|
Output output() {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
# And jars:
|
# And jars:
|
||||||
# (3) Java API .jar
|
# (3) Java API .jar
|
||||||
# (4) Java API sources .jar
|
# (4) Java API sources .jar
|
||||||
# (5) Java Op wrappers .jar
|
|
||||||
# (6) Java Op wrapper sources .jar
|
|
||||||
#
|
#
|
||||||
# These binary distributions will allow use of TensorFlow in various languages
|
# These binary distributions will allow use of TensorFlow in various languages
|
||||||
# without having to compile the TensorFlow framework from sources, which takes
|
# without having to compile the TensorFlow framework from sources, which takes
|
||||||
@ -36,8 +34,6 @@
|
|||||||
# - lib_package/libtensorflow_jni${SUFFIX}.tar.gz
|
# - lib_package/libtensorflow_jni${SUFFIX}.tar.gz
|
||||||
# - lib_package/libtensorflow.jar
|
# - lib_package/libtensorflow.jar
|
||||||
# - lib_package/libtensorflow-src.jar
|
# - lib_package/libtensorflow-src.jar
|
||||||
# - lib_package/libtensorflow_op.jar
|
|
||||||
# - lib_package/libtensorflow_op-src.jar
|
|
||||||
# - lib_package/libtensorflow_proto.zip
|
# - lib_package/libtensorflow_proto.zip
|
||||||
#
|
#
|
||||||
# ASSUMPTIONS:
|
# ASSUMPTIONS:
|
||||||
@ -79,15 +75,12 @@ function build_libtensorflow_tarball() {
|
|||||||
//tensorflow/tools/lib_package:libtensorflow_jni.tar.gz \
|
//tensorflow/tools/lib_package:libtensorflow_jni.tar.gz \
|
||||||
//tensorflow/java:libtensorflow.jar \
|
//tensorflow/java:libtensorflow.jar \
|
||||||
//tensorflow/java:libtensorflow-src.jar \
|
//tensorflow/java:libtensorflow-src.jar \
|
||||||
//tensorflow/java:libtensorflow_op.jar \
|
|
||||||
//tensorflow/java:libtensorflow_op-src.jar \
|
|
||||||
//tensorflow/tools/lib_package:libtensorflow_proto.zip
|
//tensorflow/tools/lib_package:libtensorflow_proto.zip
|
||||||
|
|
||||||
mkdir -p ${DIR}
|
mkdir -p ${DIR}
|
||||||
cp bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz ${DIR}/libtensorflow${TARBALL_SUFFIX}.tar.gz
|
cp bazel-bin/tensorflow/tools/lib_package/libtensorflow.tar.gz ${DIR}/libtensorflow${TARBALL_SUFFIX}.tar.gz
|
||||||
cp bazel-bin/tensorflow/tools/lib_package/libtensorflow_jni.tar.gz ${DIR}/libtensorflow_jni${TARBALL_SUFFIX}.tar.gz
|
cp bazel-bin/tensorflow/tools/lib_package/libtensorflow_jni.tar.gz ${DIR}/libtensorflow_jni${TARBALL_SUFFIX}.tar.gz
|
||||||
cp bazel-bin/tensorflow/java/libtensorflow.jar bazel-bin/tensorflow/java/libtensorflow-src.jar ${DIR}
|
cp bazel-bin/tensorflow/java/libtensorflow.jar bazel-bin/tensorflow/java/libtensorflow-src.jar ${DIR}
|
||||||
cp bazel-bin/tensorflow/java/libtensorflow_op.jar bazel-bin/tensorflow/java/libtensorflow_op-src.jar ${DIR}
|
|
||||||
cp bazel-genfiles/tensorflow/tools/lib_package/libtensorflow_proto.zip ${DIR}
|
cp bazel-genfiles/tensorflow/tools/lib_package/libtensorflow_proto.zip ${DIR}
|
||||||
chmod -x ${DIR}/*
|
chmod -x ${DIR}/*
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user