Support specifying output names during TF_Function creation

PiperOrigin-RevId: 169245946
This commit is contained in:
Igor Ganichev 2017-09-19 08:41:25 -07:00 committed by TensorFlower Gardener
parent e4223cbd75
commit ec962ff638
5 changed files with 214 additions and 49 deletions

View File

@ -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,

View File

@ -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

View File

@ -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 "

View File

@ -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;
}

View File

@ -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);