Support specifying output names during TF_Function creation
PiperOrigin-RevId: 169245946
This commit is contained in:
parent
e4223cbd75
commit
ec962ff638
@ -1111,9 +1111,6 @@ TF_CAPI_EXPORT void TF_AddGradients(TF_Graph* g, TF_Output* y, int ny,
|
||||
// calling TF_DeleteFunction.
|
||||
//
|
||||
// On failure, null.
|
||||
//
|
||||
// TODO(iga): Add input_names argument and get output_names working (they are
|
||||
// currently ignored)
|
||||
TF_CAPI_EXPORT extern TF_Function* TF_GraphToFunction(
|
||||
const TF_Graph* fn_body, const char* fn_name, int num_opers,
|
||||
const TF_Operation* const* opers, int ninputs, const TF_Output* inputs,
|
||||
|
@ -49,6 +49,10 @@ class NodeNameMapping {
|
||||
// Make the node name unique.
|
||||
string Uniquify(const string& name);
|
||||
|
||||
// Records name as a used name. If this name is already used,
|
||||
// returns an error status.
|
||||
Status UseOutputName(const string& name);
|
||||
|
||||
// Look up how a node name was previously normalized/uniquified.
|
||||
// Returns empty if name was never seen.
|
||||
string Lookup(const string& name) const;
|
||||
@ -117,6 +121,16 @@ string NodeNameMapping::Uniquify(const string& name) {
|
||||
return uniqued;
|
||||
}
|
||||
|
||||
Status NodeNameMapping::UseOutputName(const string& name) {
|
||||
const auto& iter = used_names_.find(name);
|
||||
if (iter != used_names_.end()) {
|
||||
return InvalidArgument("Cannot have duplicate output names. Name '", name,
|
||||
"' appears more than once in 'output_names' array.");
|
||||
}
|
||||
used_names_.insert(iter, name);
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
string NodeNameMapping::Lookup(const string& name) const {
|
||||
const auto iter = name_mapping_.find(name);
|
||||
if (iter == name_mapping_.end()) return string();
|
||||
@ -228,6 +242,10 @@ Status GraphToFunctionDef(const Graph& fn_body, const string& fn_name,
|
||||
const std::vector<OutputTensor>& outputs,
|
||||
const std::vector<string>& output_names,
|
||||
FunctionDef* fdef) {
|
||||
if (!output_names.empty()) {
|
||||
DCHECK_EQ(output_names.size(), outputs.size());
|
||||
}
|
||||
|
||||
fdef->mutable_signature()->set_name(fn_name);
|
||||
|
||||
// Keep track of names we used and how we normalized them.
|
||||
@ -243,6 +261,24 @@ Status GraphToFunctionDef(const Graph& fn_body, const string& fn_name,
|
||||
// e.g. {Add:3 -> add_0:z:1}
|
||||
std::unordered_map<string, string> tensor_renaming;
|
||||
|
||||
// Fill outputs in function's signature.
|
||||
// We fill the outputs first to prevent output_names from colliding
|
||||
// with the input names we pick below. With this order, no names are used in
|
||||
// node_names yet, and output_names won't collide with anything (except
|
||||
// potentially with themselves).
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
const Node* node = outputs[i].node;
|
||||
int idx = outputs[i].index;
|
||||
OpDef::ArgDef* argdef = fdef->mutable_signature()->add_output_arg();
|
||||
argdef->set_type(node->output_type(idx));
|
||||
if (!output_names.empty()) {
|
||||
TF_RETURN_IF_ERROR(node_names.UseOutputName(output_names[i]));
|
||||
argdef->set_name(output_names[i]);
|
||||
} else {
|
||||
argdef->set_name(node_names.GetIOName(node->name()));
|
||||
}
|
||||
}
|
||||
|
||||
// Fill inputs in function's signature.
|
||||
for (size_t i = 0; i < inputs.size(); ++i) {
|
||||
const Node* node = inputs[i].node;
|
||||
@ -254,15 +290,6 @@ Status GraphToFunctionDef(const Graph& fn_body, const string& fn_name,
|
||||
tensor_renaming[strings::StrCat(node->name(), ":", idx)] = input_name;
|
||||
}
|
||||
|
||||
// Fill outputs in function's signature.
|
||||
for (size_t i = 0; i < outputs.size(); ++i) {
|
||||
const Node* node = outputs[i].node;
|
||||
int idx = outputs[i].index;
|
||||
OpDef::ArgDef* argdef = fdef->mutable_signature()->add_output_arg();
|
||||
argdef->set_type(node->output_type(idx));
|
||||
argdef->set_name(node_names.GetIOName(node->name()));
|
||||
}
|
||||
|
||||
// Populate tensor_renaming and node_names.
|
||||
// Generate the new output names for every node in the function.
|
||||
// The NodeDefs in FunctionDefs use a different naming scheme for
|
||||
|
@ -149,24 +149,40 @@ class CApiFunctionTest : public ::testing::Test {
|
||||
void Define(int num_opers, const std::vector<TF_Operation*>& opers,
|
||||
const std::vector<TF_Operation*>& inputs,
|
||||
const std::vector<TF_Operation*>& outputs,
|
||||
const char** output_names, bool expect_failure = false) {
|
||||
const std::vector<string>& output_names,
|
||||
bool expect_failure = false) {
|
||||
DefineT(num_opers, opers, ToOutput(inputs), ToOutput(outputs), output_names,
|
||||
expect_failure);
|
||||
}
|
||||
|
||||
// Caller must delete[] the returned value
|
||||
static const char** ToArray(const std::vector<string>& strs) {
|
||||
const char** ptr = nullptr;
|
||||
if (!strs.empty()) {
|
||||
ptr = new const char*[strs.size()];
|
||||
for (size_t i = 0; i < strs.size(); ++i) {
|
||||
ptr[i] = strs[i].c_str();
|
||||
}
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// An explicit `num_opers` is needed so that we can distinguish between the
|
||||
// case of no operations specified (-1) and the case of an empty set of
|
||||
// operations specified (0).
|
||||
void DefineT(int num_opers, const std::vector<TF_Operation*>& opers,
|
||||
const std::vector<TF_Output>& inputs,
|
||||
const std::vector<TF_Output>& outputs, const char** output_names,
|
||||
const std::vector<TF_Output>& outputs,
|
||||
const std::vector<string>& output_names,
|
||||
bool expect_failure = false) {
|
||||
ASSERT_EQ(func_, nullptr);
|
||||
const char** output_names_ptr = ToArray(output_names);
|
||||
func_ = TF_GraphToFunction(func_graph_, func_name_, num_opers,
|
||||
num_opers == -1 ? nullptr : opers.data(),
|
||||
inputs.size(), inputs.data(), outputs.size(),
|
||||
outputs.data(), output_names,
|
||||
outputs.data(), output_names_ptr,
|
||||
/*opts=*/nullptr, s_);
|
||||
delete[] output_names_ptr;
|
||||
if (expect_failure) {
|
||||
ASSERT_EQ(func_, nullptr);
|
||||
return;
|
||||
@ -357,7 +373,7 @@ TEST_F(CApiFunctionTest, OneOp_ZeroInputs_OneOutput) {
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* c = ScalarConst(10, func_graph_, s_, "scalar10");
|
||||
Define(-1, {}, {}, {c}, nullptr);
|
||||
Define(-1, {}, {}, {c}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_op = Use({});
|
||||
@ -377,7 +393,7 @@ TEST_F(CApiFunctionTest, OneOp_OneInput_OneOutput) {
|
||||
// Define
|
||||
TF_Operation* feed = Placeholder(func_graph_, s_);
|
||||
TF_Operation* neg = Neg(feed, func_graph_, s_);
|
||||
Define(-1, {}, {feed}, {neg}, nullptr);
|
||||
Define(-1, {}, {feed}, {neg}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
@ -387,6 +403,48 @@ TEST_F(CApiFunctionTest, OneOp_OneInput_OneOutput) {
|
||||
{{"feed", "neg_0:0"}, {"neg_0:y:0", "neg"}}, {});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, OneOutput_OutputNames) {
|
||||
/*
|
||||
* |
|
||||
* v
|
||||
* negate
|
||||
* |
|
||||
* v
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* feed = Placeholder(func_graph_, s_);
|
||||
TF_Operation* neg = Neg(feed, func_graph_, s_);
|
||||
Define(-1, {}, {feed}, {neg}, {"negated_num"});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({func_feed});
|
||||
Run({{func_feed, Int32Tensor(3)}}, func_op, -3);
|
||||
VerifyFDef({"neg"}, {{"feed", DT_INT32}}, {{"negated_num", DT_INT32}},
|
||||
{{"feed", "neg:0"}, {"neg:y:0", "negated_num"}}, {});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, OutputNames_SameNameAsInput) {
|
||||
/*
|
||||
* |
|
||||
* v
|
||||
* negate
|
||||
* |
|
||||
* v
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* feed = Placeholder(func_graph_, s_, "negation");
|
||||
TF_Operation* neg = Neg(feed, func_graph_, s_, "neg");
|
||||
Define(-1, {}, {feed}, {neg}, {"negation"});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({func_feed});
|
||||
Run({{func_feed, Int32Tensor(3)}}, func_op, -3);
|
||||
VerifyFDef({"neg"}, {{"negation_0", DT_INT32}}, {{"negation", DT_INT32}},
|
||||
{{"negation_0", "neg:0"}, {"neg:y:0", "negation"}}, {});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, ZeroOps_Identity) {
|
||||
/*
|
||||
* |
|
||||
@ -396,14 +454,14 @@ TEST_F(CApiFunctionTest, ZeroOps_Identity) {
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* feed = Placeholder(func_graph_, s_);
|
||||
Define(-1, {}, {feed}, {feed}, nullptr);
|
||||
Define(-1, {}, {feed}, {feed}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({func_feed});
|
||||
Run({{func_feed, Int32Tensor(3)}}, func_op, 3);
|
||||
VerifyFDef(empty_, {{"feed", DT_INT32}}, {{"feed_0", DT_INT32}},
|
||||
{{"feed", "feed_0"}}, {});
|
||||
VerifyFDef(empty_, {{"feed_0", DT_INT32}}, {{"feed", DT_INT32}},
|
||||
{{"feed_0", "feed"}}, {});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, ZeroOps_Permutation) {
|
||||
@ -420,15 +478,40 @@ TEST_F(CApiFunctionTest, ZeroOps_Permutation) {
|
||||
// Define
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
Define(-1, {}, {feed1, feed2}, {feed2, feed1}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2}, {feed2, feed1}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({two, func_feed});
|
||||
Run({{func_feed, Int32Tensor(3)}}, {{func_op, 0}, {func_op, 1}}, {3, 2});
|
||||
VerifyFDef(empty_, M({{"feed1"}, {"feed2"}}), M({{"feed2_0"}, {"feed1_0"}}),
|
||||
{{"feed1", "feed1_0"}, {"feed2", "feed2_0"}}, {});
|
||||
VerifyFDef(empty_, M({{"feed1_0"}, {"feed2_0"}}), M({{"feed2"}, {"feed1"}}),
|
||||
{{"feed1_0", "feed1"}, {"feed2_0", "feed2"}}, {});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, ZeroOps_Permutation_OutputNames) {
|
||||
/*
|
||||
* | |
|
||||
* \ /
|
||||
* \/
|
||||
* x
|
||||
* /\
|
||||
* / \
|
||||
* | |
|
||||
* v v
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
Define(-1, {}, {feed1, feed2}, {feed2, feed1}, {"first", "second"});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({two, func_feed});
|
||||
Run({{func_feed, Int32Tensor(3)}}, {{func_op, 0}, {func_op, 1}}, {3, 2});
|
||||
VerifyFDef(empty_, M({{"feed1"}, {"feed2"}}), M({{"first"}, {"second"}}),
|
||||
{{"feed1", "second"}, {"feed2", "first"}}, {});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, OneOp_TwoInputs_OneOutput) {
|
||||
@ -443,7 +526,7 @@ TEST_F(CApiFunctionTest, OneOp_TwoInputs_OneOutput) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
Define(-1, {}, {feed1, feed2}, {add}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2}, {add}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
@ -467,7 +550,7 @@ TEST_F(CApiFunctionTest, OneOp_TwoInputs_ZeroOutputs) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
Add(feed1, feed2, func_graph_, s_);
|
||||
Define(-1, {}, {feed1, feed2}, {}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2}, {}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
@ -494,7 +577,7 @@ TEST_F(CApiFunctionTest, TwoOps_ThreeInputs_OneOutput) {
|
||||
TF_Operation* feed3 = Placeholder(func_graph_, s_, "feed3");
|
||||
TF_Operation* add1 = Add(feed1, feed2, func_graph_, s_, "add1");
|
||||
TF_Operation* add2 = Add(add1, feed3, func_graph_, s_, "add2");
|
||||
Define(-1, {}, {feed1, feed2, feed3}, {add2}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2, feed3}, {add2}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_, "two");
|
||||
@ -526,7 +609,7 @@ TEST_F(CApiFunctionTest, OneOp_TwoInputs_TwoDuplicateOutputs) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
Define(-1, {}, {feed1, feed2}, {add, add}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2}, {add, add}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
@ -541,6 +624,35 @@ TEST_F(CApiFunctionTest, OneOp_TwoInputs_TwoDuplicateOutputs) {
|
||||
{});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, TwoDuplicateOutputs_OutputNames) {
|
||||
/*
|
||||
* | |
|
||||
* v v
|
||||
* add
|
||||
* |
|
||||
* +-+-+
|
||||
* | |
|
||||
* v v
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
Define(-1, {}, {feed1, feed2}, {add, add}, {"out1", "out2"});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({two, func_feed});
|
||||
Run({{func_feed, Int32Tensor(3)}}, {{func_op, 0}, {func_op, 1}}, {5, 5});
|
||||
VerifyFDef({"add"}, M({{"feed1"}, {"feed2"}}), M({{"out1"}, {"out2"}}),
|
||||
{{"feed1", "add:0"},
|
||||
{"feed2", "add:1"},
|
||||
{"add:sum:0", "out1"},
|
||||
{"add:sum:0", "out2"}},
|
||||
{});
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, TwoOps_ThreeInputs_TwoOutputs) {
|
||||
/*
|
||||
* | | |
|
||||
@ -560,7 +672,7 @@ TEST_F(CApiFunctionTest, TwoOps_ThreeInputs_TwoOutputs) {
|
||||
TF_Operation* feed3 = Placeholder(func_graph_, s_, "feed3");
|
||||
TF_Operation* add1 = Add(feed1, feed2, func_graph_, s_, "add1");
|
||||
TF_Operation* add2 = Add(add1, feed3, func_graph_, s_, "add2");
|
||||
Define(-1, {}, {feed1, feed2, feed3}, {add1, add2}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2, feed3}, {add1, add2}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_, "two");
|
||||
@ -600,7 +712,7 @@ TEST_F(CApiFunctionTest, FromSubsetOfOps) {
|
||||
TF_Operation* feed3 = Placeholder(func_graph_, s_, "feed3");
|
||||
TF_Operation* add1 = Add(feed1, feed2, func_graph_, s_, "add1");
|
||||
TF_Operation* add2 = Add(add1, feed3, func_graph_, s_, "add2");
|
||||
Define(1, {add2}, {add1, feed3}, {add2}, nullptr);
|
||||
Define(1, {add2}, {add1, feed3}, {add2}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_, "two");
|
||||
@ -634,7 +746,7 @@ TEST_F(CApiFunctionTest, UsingOneOutputOfSplit) {
|
||||
// Define
|
||||
TF_Operation* feed = Placeholder(func_graph_, s_);
|
||||
TF_Operation* split = Split3(feed, func_graph_, s_);
|
||||
DefineT(-1, {}, {{feed, 0}}, {{split, 1}}, nullptr);
|
||||
DefineT(-1, {}, {{feed, 0}}, {{split, 1}}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
@ -669,7 +781,7 @@ TEST_F(CApiFunctionTest, UsingTwoOutputsOfSplit) {
|
||||
// Define
|
||||
TF_Operation* feed = Placeholder(func_graph_, s_);
|
||||
TF_Operation* split = Split3(feed, func_graph_, s_);
|
||||
DefineT(-1, {}, {{feed, 0}}, {{split, 0}, {split, 2}}, nullptr);
|
||||
DefineT(-1, {}, {{feed, 0}}, {{split, 0}, {split, 2}}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
@ -708,7 +820,7 @@ TEST_F(CApiFunctionTest, UsingTwoOutputsOfSplitAsInputs) {
|
||||
TF_Operation* split = Split3(feed, func_graph_, s_);
|
||||
TF_Operation* add = Add({split, 0}, {split, 2}, func_graph_, s_);
|
||||
ASSERT_EQ(TF_OK, TF_GetCode(s_)) << TF_Message(s_);
|
||||
DefineT(1, {add}, {{split, 0}, {split, 2}}, {{add, 0}}, nullptr);
|
||||
DefineT(1, {add}, {{split, 0}, {split, 2}}, {{add, 0}}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_, "two");
|
||||
@ -744,7 +856,7 @@ TEST_F(CApiFunctionTest, NodesUsedInInputsMustHaveSingleOutput) {
|
||||
TF_Operation* split = Split3(c, func_graph_, s_);
|
||||
TF_Operation* add = Add({split, 0}, {split, 2}, func_graph_, s_);
|
||||
ASSERT_EQ(TF_OK, TF_GetCode(s_)) << TF_Message(s_);
|
||||
DefineT(-1, {}, {{split, 0}, {split, 2}}, {{add, 0}}, nullptr, true);
|
||||
DefineT(-1, {}, {{split, 0}, {split, 2}}, {{add, 0}}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("When `num_opers` is set to -1, nodes referenced in "
|
||||
"`inputs` must have a single output. Node split3 has "
|
||||
@ -797,7 +909,7 @@ TEST_F(CApiFunctionTest, FunctionWithWhileLoop) {
|
||||
}
|
||||
|
||||
// Define function, use it in graph, and run
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 0}}, {outputs[0]}, nullptr);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 0}}, {outputs[0]}, {});
|
||||
TF_Operation* five = ScalarConst(5, host_graph_, s_, "five");
|
||||
TF_Operation* func_feed = Placeholder(host_graph_, s_);
|
||||
TF_Operation* func_op = Use({func_feed, five});
|
||||
@ -835,7 +947,7 @@ TEST_F(CApiFunctionTest, ControlDependency) {
|
||||
TF_Operation* add =
|
||||
AddWithCtrlDependency(feed1, feed2, func_graph_, five, s_);
|
||||
EXPECT_EQ(TF_OK, TF_GetCode(s_)) << TF_Message(s_);
|
||||
Define(-1, {}, {feed1, feed2}, {add}, nullptr);
|
||||
Define(-1, {}, {feed1, feed2}, {add}, {});
|
||||
|
||||
// Use, run, and verify
|
||||
TF_Operation* two = ScalarConst(2, host_graph_, s_);
|
||||
@ -864,7 +976,7 @@ TEST_F(CApiFunctionTest, ControlDependencyOutsideOfBody) {
|
||||
TF_Operation* add =
|
||||
AddWithCtrlDependency(feed1, feed2, func_graph_, five, s_);
|
||||
EXPECT_EQ(TF_OK, TF_GetCode(s_)) << TF_Message(s_);
|
||||
Define(1, {add}, {feed1, feed2}, {add}, nullptr, true);
|
||||
Define(1, {add}, {feed1, feed2}, {add}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("The source of control edge [id=3 scalar:-1 -> add:-1] "
|
||||
"is not in the body. Encountered while creating "
|
||||
@ -888,7 +1000,7 @@ TEST_F(CApiFunctionTest, ControlDependencyOutsideOfBody_FromInputNode) {
|
||||
TF_Operation* add =
|
||||
AddWithCtrlDependency(feed1, feed2, func_graph_, feed1, s_);
|
||||
EXPECT_EQ(TF_OK, TF_GetCode(s_)) << TF_Message(s_);
|
||||
Define(-1, {}, {feed1, feed2}, {add}, nullptr, true);
|
||||
Define(-1, {}, {feed1, feed2}, {add}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("The source of control edge [id=3 feed1:-1 -> add:-1] "
|
||||
"is not in the body. Encountered while creating "
|
||||
@ -914,13 +1026,40 @@ TEST_F(CApiFunctionTest, DuplicateInputsAreNotAllowed) {
|
||||
*/
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* add = Add(feed1, feed1, func_graph_, s_);
|
||||
Define(-1, {}, {feed1, feed1}, {add}, nullptr, true);
|
||||
Define(-1, {}, {feed1, feed1}, {add}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(
|
||||
string("TF_Output feed1:0 appears more than once in the input list"),
|
||||
string(TF_Message(s_)));
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, DuplicateOutputNamesAreNotAllowed) {
|
||||
/*
|
||||
* | | |
|
||||
* v v /
|
||||
* add /
|
||||
* | |
|
||||
* +-+ |
|
||||
* | | |
|
||||
* | v v
|
||||
* | add
|
||||
* | |
|
||||
* v v
|
||||
*/
|
||||
// Define
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* feed3 = Placeholder(func_graph_, s_, "feed3");
|
||||
TF_Operation* add1 = Add(feed1, feed2, func_graph_, s_, "add1");
|
||||
TF_Operation* add2 = Add(add1, feed3, func_graph_, s_, "add2");
|
||||
Define(-1, {}, {feed1, feed2, feed3}, {add1, add2}, {"my_out", "my_out"},
|
||||
true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("Cannot have duplicate output names. Name 'my_out' "
|
||||
"appears more than once in 'output_names' array."),
|
||||
string(TF_Message(s_)));
|
||||
}
|
||||
|
||||
TEST_F(CApiFunctionTest, InvalidInputTensor_HighIndex) {
|
||||
/*
|
||||
* | |
|
||||
@ -932,7 +1071,7 @@ TEST_F(CApiFunctionTest, InvalidInputTensor_HighIndex) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 2}}, {{add, 0}}, nullptr, true);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 2}}, {{add, 0}}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("Node 'feed2' (type: 'Placeholder', num of outputs: 1) does "
|
||||
"not have output 2\n\tEncountered while processing "
|
||||
@ -951,7 +1090,7 @@ TEST_F(CApiFunctionTest, InvalidInputTensor_BadNodePtr) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
DefineT(-1, {}, {{feed1, 0}, {nullptr, 0}}, {{add, 0}}, nullptr, true);
|
||||
DefineT(-1, {}, {{feed1, 0}, {nullptr, 0}}, {{add, 0}}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("Node is null\n\tEncountered while processing input 1 "
|
||||
"into function 'MyFunc'"),
|
||||
@ -969,7 +1108,7 @@ TEST_F(CApiFunctionTest, InvalidOutputTensor_HighIndex) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 0}}, {{add, 3}}, nullptr, true);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 0}}, {{add, 3}}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("Node 'add' (type: 'AddN', num of outputs: 1) does "
|
||||
"not have output 3\n\tEncountered while processing "
|
||||
@ -988,7 +1127,7 @@ TEST_F(CApiFunctionTest, InvalidOutputTensor_BadNodePtr) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
Add(feed1, feed2, func_graph_, s_);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 0}}, {{nullptr, 3}}, nullptr, true);
|
||||
DefineT(-1, {}, {{feed1, 0}, {feed2, 0}}, {{nullptr, 3}}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("Node is null\n\tEncountered while processing output 0 "
|
||||
"from function 'MyFunc'"),
|
||||
@ -1006,7 +1145,7 @@ TEST_F(CApiFunctionTest, NodeMissingInput) {
|
||||
TF_Operation* feed1 = Placeholder(func_graph_, s_, "feed1");
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
DefineT(1, {add}, {{feed1, 0}}, {{add, 0}}, nullptr, true);
|
||||
DefineT(1, {add}, {{feed1, 0}}, {{add, 0}}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("Input 1, 'feed2:0', of node 'add' in function 'MyFunc' "
|
||||
"is not available. You might need to include it in inputs "
|
||||
@ -1027,7 +1166,7 @@ TEST_F(CApiFunctionTest, OutputOpNotInBody) {
|
||||
TF_Operation* feed2 = Placeholder(func_graph_, s_, "feed2");
|
||||
TF_Operation* scalar = ScalarConst(2, func_graph_, s_);
|
||||
TF_Operation* add = Add(feed1, feed2, func_graph_, s_);
|
||||
Define(1, {add}, {feed1, feed2}, {add, scalar}, nullptr, true);
|
||||
Define(1, {add}, {feed1, feed2}, {add, scalar}, {}, true);
|
||||
EXPECT_EQ(TF_INVALID_ARGUMENT, TF_GetCode(s_));
|
||||
EXPECT_EQ(string("TF_Output scalar:0 is neither in the function body nor "
|
||||
"among function inputs. Encountered while creating "
|
||||
|
@ -168,9 +168,9 @@ TF_Operation* Add(TF_Output l, TF_Output r, TF_Graph* graph, TF_Status* s,
|
||||
return TF_FinishOperation(desc, s);
|
||||
}
|
||||
|
||||
void NegHelper(TF_Operation* n, TF_Graph* graph, TF_Status* s,
|
||||
void NegHelper(TF_Operation* n, TF_Graph* graph, TF_Status* s, const char* name,
|
||||
TF_Operation** op) {
|
||||
TF_OperationDescription* desc = TF_NewOperation(graph, "Neg", "neg");
|
||||
TF_OperationDescription* desc = TF_NewOperation(graph, "Neg", name);
|
||||
TF_Output neg_input = {n, 0};
|
||||
TF_AddInput(desc, neg_input);
|
||||
*op = TF_FinishOperation(desc, s);
|
||||
@ -178,9 +178,10 @@ void NegHelper(TF_Operation* n, TF_Graph* graph, TF_Status* s,
|
||||
ASSERT_NE(*op, nullptr);
|
||||
}
|
||||
|
||||
TF_Operation* Neg(TF_Operation* n, TF_Graph* graph, TF_Status* s) {
|
||||
TF_Operation* Neg(TF_Operation* n, TF_Graph* graph, TF_Status* s,
|
||||
const char* name) {
|
||||
TF_Operation* op;
|
||||
NegHelper(n, graph, s, &op);
|
||||
NegHelper(n, graph, s, name, &op);
|
||||
return op;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,8 @@ TF_Operation* AddWithCtrlDependency(TF_Operation* l, TF_Operation* r,
|
||||
TF_Operation* Add(TF_Output l, TF_Output r, TF_Graph* graph, TF_Status* s,
|
||||
const char* name = "add");
|
||||
|
||||
TF_Operation* Neg(TF_Operation* n, TF_Graph* graph, TF_Status* s);
|
||||
TF_Operation* Neg(TF_Operation* n, TF_Graph* graph, TF_Status* s,
|
||||
const char* name = "neg");
|
||||
|
||||
TF_Operation* LessThan(TF_Output l, TF_Output r, TF_Graph* graph, TF_Status* s);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user