Skip to content

Commit 8d0056f

Browse files
committed
Merge commit for internal changes
2 parents bab2db4 + ead3cd6 commit 8d0056f

104 files changed

Lines changed: 2847 additions & 981 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

WORKSPACE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ load("//tensorflow:workspace.bzl", "tf_workspace")
2727
# path = "<PATH_TO_SDK>",
2828
#)
2929
#
30-
# Android NDK r12b is recommended (higher may cause issues with Bazel)
3130
#android_ndk_repository(
3231
# name="androidndk",
3332
# path="<PATH_TO_NDK>",

tensorflow/c/c_test_util.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ static void Int32Deallocator(void* data, size_t, void* arg) {
2727
delete[] static_cast<int32_t*>(data);
2828
}
2929

30+
static void DoubleDeallocator(void* data, size_t, void* arg) {
31+
delete[] static_cast<double*>(data);
32+
}
33+
3034
TF_Tensor* Int8Tensor(const int64_t* dims, int num_dims, const char* values) {
3135
int64_t num_values = 1;
3236
for (int i = 0; i < num_dims; ++i) {
@@ -63,6 +67,14 @@ TF_Tensor* Int32Tensor(int32_t v) {
6367
&Int32Deallocator, nullptr);
6468
}
6569

70+
TF_Tensor* DoubleTensor(double v) {
71+
const int num_bytes = sizeof(double);
72+
double* values = new double[1];
73+
values[0] = v;
74+
return TF_NewTensor(TF_DOUBLE, nullptr, 0, values, num_bytes,
75+
&DoubleDeallocator, nullptr);
76+
}
77+
6678
// All the *Helper methods are used as a workaround for the restrictions that
6779
// one cannot call ASSERT_* methods in non-void-returning functions (when
6880
// exceptions are disabled during compilation)
@@ -105,6 +117,12 @@ TF_Operation* ScalarConst(int32_t v, TF_Graph* graph, TF_Status* s,
105117
return Const(tensor.get(), graph, s, name);
106118
}
107119

120+
TF_Operation* ScalarConst(double v, TF_Graph* graph, TF_Status* s,
121+
const char* name) {
122+
unique_tensor_ptr tensor(DoubleTensor(v), TF_DeleteTensor);
123+
return Const(tensor.get(), graph, s, name);
124+
}
125+
108126
void AddHelper(TF_Operation* l, TF_Operation* r, TF_Graph* graph, TF_Status* s,
109127
const char* name, TF_Operation** op, bool check) {
110128
TF_OperationDescription* desc = TF_NewOperation(graph, "AddN", name);

tensorflow/c/c_test_util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ TF_Tensor* Int32Tensor(const std::vector<int32_t>& values);
4242

4343
TF_Tensor* Int32Tensor(int32_t v);
4444

45+
TF_Tensor* DoubleTensor(double v);
46+
4547
TF_Operation* Placeholder(TF_Graph* graph, TF_Status* s,
4648
const char* name = "feed");
4749

@@ -51,6 +53,9 @@ TF_Operation* Const(TF_Tensor* t, TF_Graph* graph, TF_Status* s,
5153
TF_Operation* ScalarConst(int32_t v, TF_Graph* graph, TF_Status* s,
5254
const char* name = "scalar");
5355

56+
TF_Operation* ScalarConst(double v, TF_Graph* graph, TF_Status* s,
57+
const char* name = "scalar");
58+
5459
TF_Operation* Add(TF_Operation* l, TF_Operation* r, TF_Graph* graph,
5560
TF_Status* s, const char* name = "add");
5661

tensorflow/c/eager/c_api.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ TFE_TensorHandle* TFE_TensorHandleCopyToDevice(TFE_TensorHandle* h,
226226
tensorflow::Tensor dst(
227227
dstd->GetAllocator(tensorflow::AllocatorAttributes()), src->dtype(),
228228
src->shape());
229+
if (src->shape().num_elements() == 0) {
230+
return new TFE_TensorHandle(dst, dstd);
231+
}
229232
tensorflow::Notification n;
230233
dstd->tensorflow_gpu_device_info()->default_context->CopyCPUTensorToDevice(
231234
src, dstd, &dst, [status, &n](const tensorflow::Status& s) {

tensorflow/c/while_loop_test.cc

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,20 +288,86 @@ TEST_F(CApiWhileLoopTest, NestedLoop) {
288288
ExpectOutputValue(1, 3);
289289
}
290290

291-
TEST_F(CApiWhileLoopTest, BadCondOutput) {
291+
TEST_F(CApiWhileLoopTest, UnsetCondOutput) {
292292
Init(1);
293293
params_->body_outputs[0] = params_->body_inputs[0];
294294
ExpectError(TF_INVALID_ARGUMENT,
295295
"TF_WhileParams `cond_output` field isn't set");
296296
}
297297

298-
TEST_F(CApiWhileLoopTest, BadBodyOutput) {
298+
TEST_F(CApiWhileLoopTest, WrongCondOutputType) {
299+
Init(1);
300+
params_->cond_output = params_->cond_inputs[0];
301+
params_->body_outputs[0] = params_->body_inputs[0];
302+
ExpectError(TF_INVALID_ARGUMENT,
303+
"BuildWhileLoop: 'cond' argument must return a boolean output, "
304+
"got int32");
305+
}
306+
307+
TEST_F(CApiWhileLoopTest, InvalidCondOutputNode) {
308+
Init(1);
309+
// Try to reuse node from parent graph
310+
params_->cond_output = inputs_[0];
311+
params_->body_outputs[0] = params_->body_inputs[0];
312+
// TODO(skyewm): this error message could be more informative. Add explicit
313+
// checks for this case in the while loop implementation?
314+
ExpectError(TF_INVALID_ARGUMENT,
315+
"Requested return node 'p0' not found in graph def");
316+
}
317+
318+
TEST_F(CApiWhileLoopTest, InvalidCondOutputIndex) {
319+
Init(1);
320+
CreateCondGraph();
321+
params_->cond_output.index = 100;
322+
params_->body_outputs[0] = params_->body_inputs[0];
323+
ExpectError(TF_INVALID_ARGUMENT,
324+
"Invalid return output 100 of node 'less_than', which has 1 "
325+
"output(s)");
326+
}
327+
328+
// TODO(skyewm): test bad cond output shape
329+
330+
TEST_F(CApiWhileLoopTest, UnsetBodyOutput) {
299331
Init(1);
300332
CreateCondGraph();
301333
ExpectError(TF_INVALID_ARGUMENT,
302334
"TF_WhileParams `body_outputs[0]` field isn't set");
303335
}
304336

337+
// TODO(skyewm): enable this when it works (currently doesn't error)
338+
// TEST_F(CApiWhileLoopTest, WrongBodyOutputType) {
339+
// Init(1);
340+
// CreateCondGraph();
341+
// TF_Operation* double_scalar =
342+
// ScalarConst(1.0, params_->body_graph, s_, "double_scalar");
343+
// params_->body_outputs[0] = {double_scalar, 0};
344+
// ExpectError(TF_INVALID_ARGUMENT, "bad body output type");
345+
// }
346+
347+
TEST_F(CApiWhileLoopTest, InvalidBodyOutputNode) {
348+
Init(1);
349+
CreateCondGraph();
350+
// Try to reuse node from parent graph
351+
params_->body_outputs[0] = inputs_[0];
352+
// TODO(skyewm): this error message could be more informative. Add explicit
353+
// checks for this case in the while loop implementation?
354+
ExpectError(TF_INVALID_ARGUMENT,
355+
"Requested return node 'p0' not found in graph def");
356+
}
357+
358+
// TODO(skyewm): enable this when it works (currently segfaults!)
359+
// TEST_F(CApiWhileLoopTest, InvalidBodyOutputIndex) {
360+
// Init(1);
361+
// CreateCondGraph();
362+
// params_->body_outputs[0] = params_->body_inputs[0];
363+
// params_->body_outputs[0].index = 100;
364+
// ExpectError(TF_INVALID_ARGUMENT,
365+
// "Invalid return output 100 of node 'less_than', which has 1 "
366+
// "output(s)");
367+
// }
368+
369+
// TODO(skyewm): test bad body output shape
370+
305371
TEST_F(CApiWhileLoopTest, NullName) {
306372
Init(1);
307373
CreateCondGraph();

tensorflow/cc/BUILD

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,21 @@ cc_library_with_android_deps(
248248
],
249249
)
250250

251+
tf_cc_test(
252+
name = "ops_while_loop_test",
253+
size = "small",
254+
srcs = ["ops/while_loop_test.cc"],
255+
deps = [
256+
":cc_ops",
257+
":client_session",
258+
":testutil",
259+
":while_loop",
260+
"//tensorflow/core:test",
261+
"//tensorflow/core:test_main",
262+
"//tensorflow/core:testlib",
263+
],
264+
)
265+
251266
cc_library(
252267
name = "grad_op_registry",
253268
srcs = ["framework/grad_op_registry.cc"],

tensorflow/cc/ops/while_loop.cc

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,16 @@ Status CreateCond(const Scope& scope, const CondGraphBuilderFn& cond,
102102
scope.NewSubScope("cond").WithControlDependencies(inputs[0]);
103103
Output raw_cond_out;
104104
TF_RETURN_IF_ERROR(cond(cond_scope, inputs, &raw_cond_out));
105+
106+
TF_RETURN_IF_ERROR(scope.graph()->IsValidOutputTensor(raw_cond_out.node(),
107+
raw_cond_out.index()));
105108
if (raw_cond_out.type() != DT_BOOL) {
106109
return errors::InvalidArgument(
107110
"BuildWhileLoop: 'cond' argument must return a boolean output, got ",
108111
DataTypeString(raw_cond_out.type()));
109112
}
113+
// TODO(skyewm): check that raw_cond_out is scalar
114+
110115
*output = LoopCond(scope, raw_cond_out).output;
111116
return Status::OK();
112117
}
@@ -123,13 +128,18 @@ Status CreateBody(const Scope& scope, const BodyGraphBuilderFn& body,
123128
Scope body_scope =
124129
scope.NewSubScope("body").WithControlDependencies(inputs[0]);
125130
TF_RETURN_IF_ERROR(body(body_scope, inputs, outputs));
131+
126132
const size_t num_loop_vars = inputs.size();
127133
if (outputs->size() != num_loop_vars) {
128134
return errors::InvalidArgument(
129135
"BuildWhileLoop: 'body' argument expected to return ", num_loop_vars,
130-
"outputs, got ", outputs->size());
136+
" output(s), got ", outputs->size());
137+
}
138+
for (const Output& output : *outputs) {
139+
TF_RETURN_IF_ERROR(
140+
scope.graph()->IsValidOutputTensor(output.node(), output.index()));
141+
// TODO(skyewm): check output types/shapes
131142
}
132-
// TODO(skyewm): check output types/shapes
133143
return Status::OK();
134144
}
135145

0 commit comments

Comments
 (0)