Skip to content

Commit 4e9ce43

Browse files
Convert Conv2D forward tests to run in both eager and graph modes.
PiperOrigin-RevId: 166146212
1 parent 2b4780b commit 4e9ce43

4 files changed

Lines changed: 115 additions & 75 deletions

File tree

tensorflow/python/framework/test_util.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,54 @@ def run_eager_mode():
326326
return decorator
327327

328328

329+
def is_gpu_available(cuda_only=False, min_cuda_compute_capability=None):
330+
"""Returns whether TensorFlow can access a GPU.
331+
332+
Args:
333+
cuda_only: limit the search to CUDA gpus.
334+
min_cuda_compute_capability: a (major,minor) pair that indicates the minimum
335+
CUDA compute capability required, or None if no requirement.
336+
337+
Returns:
338+
True iff a gpu device of the requested kind is available.
339+
"""
340+
341+
def compute_capability_from_device_desc(device_desc):
342+
# TODO(jingyue): The device description generator has to be in sync with
343+
# this file. Another option is to put compute capability in
344+
# DeviceAttributes, but I avoided that to keep DeviceAttributes
345+
# target-independent. Reconsider this option when we have more things like
346+
# this to keep in sync.
347+
# LINT.IfChange
348+
match = re.search(r"compute capability: (\d+)\.(\d+)", device_desc)
349+
# LINT.ThenChange(//tensorflow/core/\
350+
# common_runtime/gpu/gpu_device.cc)
351+
if not match:
352+
return 0, 0
353+
return int(match.group(1)), int(match.group(2))
354+
355+
for local_device in device_lib.list_local_devices():
356+
if local_device.device_type == "GPU":
357+
if (min_cuda_compute_capability is None or
358+
compute_capability_from_device_desc(local_device.physical_device_desc)
359+
>= min_cuda_compute_capability):
360+
return True
361+
if local_device.device_type == "SYCL" and not cuda_only:
362+
return True
363+
return False
364+
365+
366+
@contextlib.contextmanager
367+
def device(use_gpu):
368+
"""Uses gpu when requested and available."""
369+
if use_gpu and is_gpu_available():
370+
dev = "/device:GPU:0"
371+
else:
372+
dev = "/device:CPU:0"
373+
with ops.device(dev):
374+
yield
375+
376+
329377
class TensorFlowTestCase(googletest.TestCase):
330378
"""Base class for tests that need to test TensorFlow.
331379
"""

tensorflow/python/kernel_tests/conv_ops_test.py

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ def _SetupValuesForDevice(self, tensor_in_sizes, filter_in_sizes, strides,
189189
# numbers from 1.
190190
x1 = [f * 1.0 for f in range(1, total_size_1 + 1)]
191191
x2 = [f * 1.0 for f in range(1, total_size_2 + 1)]
192-
with self.test_session(use_gpu=use_gpu):
192+
193+
with test_util.device(use_gpu):
193194
t1 = constant_op.constant(x1, shape=tensor_in_sizes, dtype=dtype)
194195
t2 = constant_op.constant(x2, shape=filter_in_sizes, dtype=dtype)
195196
strides = [1] + strides + [1]
@@ -219,7 +220,7 @@ def _CompareFwdValues(self, tensor_in_sizes, filter_in_sizes, conv_strides,
219220
x2 = np.random.rand(*filter_in_sizes).astype(np.float32)
220221

221222
def _SetupVal(data_format, use_gpu):
222-
with self.test_session(use_gpu=use_gpu):
223+
with test_util.device(use_gpu):
223224
t1 = constant_op.constant(x1, shape=tensor_in_sizes)
224225
t2 = constant_op.constant(x2, shape=filter_in_sizes)
225226
strides = [1] + conv_strides + [1]
@@ -235,10 +236,9 @@ def _SetupVal(data_format, use_gpu):
235236
tensors = []
236237
for (data_format, use_gpu) in GetTestConfigs():
237238
tensors.append(_SetupVal(data_format, use_gpu))
238-
with self.test_session() as sess:
239-
values = sess.run(tensors)
240-
for i in range(1, len(values)):
241-
self.assertAllClose(values[0], values[i], rtol=1e-5, atol=1e-5)
239+
values = self.evaluate(tensors)
240+
for i in range(1, len(values)):
241+
self.assertAllClose(values[0], values[i], rtol=1e-5, atol=1e-5)
242242

243243
def _VerifyValues(self, tensor_in_sizes, filter_in_sizes, strides, padding,
244244
expected):
@@ -254,19 +254,19 @@ def _VerifyValues(self, tensor_in_sizes, filter_in_sizes, strides, padding,
254254
dtype,
255255
use_gpu=use_gpu)
256256
tensors.append(result)
257-
with self.test_session() as sess:
258-
values = sess.run(tensors)
259-
for i in range(len(tensors)):
260-
conv = tensors[i]
261-
value = values[i]
262-
print("expected = ", expected)
263-
print("actual = ", value)
264-
tol = 1e-5
265-
if value.dtype == np.float16:
266-
tol = 1e-3
267-
self.assertAllClose(expected, np.ravel(value), atol=tol, rtol=tol)
268-
self.assertShapeEqual(value, conv)
257+
values = self.evaluate(tensors)
258+
for i in range(len(tensors)):
259+
conv = tensors[i]
260+
value = values[i]
261+
print("expected = ", expected)
262+
print("actual = ", value)
263+
tol = 1e-5
264+
if value.dtype == np.float16:
265+
tol = 1e-3
266+
self.assertAllClose(expected, np.ravel(value), atol=tol, rtol=tol)
267+
self.assertShapeEqual(value, conv)
269268

269+
@test_util.run_in_graph_and_eager_modes()
270270
def testConv2D1x1Filter(self):
271271
expected_output = [
272272
30.0, 36.0, 42.0, 66.0, 81.0, 96.0, 102.0, 126.0, 150.0, 138.0, 171.0,
@@ -279,6 +279,7 @@ def testConv2D1x1Filter(self):
279279
padding="VALID",
280280
expected=expected_output)
281281

282+
@test_util.run_in_graph_and_eager_modes()
282283
def testConv2DEmpty(self):
283284
expected_output = []
284285
self._VerifyValues(
@@ -288,6 +289,7 @@ def testConv2DEmpty(self):
288289
padding="VALID",
289290
expected=expected_output)
290291

292+
@test_util.run_in_graph_and_eager_modes()
291293
def testConv2D2x2Filter(self):
292294
# The outputs are computed using third_party/py/IPython/notebook.
293295
expected_output = [2271.0, 2367.0, 2463.0, 2901.0, 3033.0, 3165.0]
@@ -298,6 +300,7 @@ def testConv2D2x2Filter(self):
298300
padding="VALID",
299301
expected=expected_output)
300302

303+
@test_util.run_in_graph_and_eager_modes()
301304
def testConv2D1x2Filter(self):
302305
# The outputs are computed using third_party/py/IPython/notebook.
303306
expected_output = [
@@ -311,6 +314,7 @@ def testConv2D1x2Filter(self):
311314
padding="VALID",
312315
expected=expected_output)
313316

317+
@test_util.run_in_graph_and_eager_modes()
314318
def testConv2D2x2FilterStride2(self):
315319
expected_output = [2271.0, 2367.0, 2463.0]
316320
self._VerifyValues(
@@ -320,6 +324,7 @@ def testConv2D2x2FilterStride2(self):
320324
padding="VALID",
321325
expected=expected_output)
322326

327+
@test_util.run_in_graph_and_eager_modes()
323328
def testConv2D2x2FilterStride2Same(self):
324329
expected_output = [2271.0, 2367.0, 2463.0, 1230.0, 1305.0, 1380.0]
325330
self._VerifyValues(
@@ -329,6 +334,7 @@ def testConv2D2x2FilterStride2Same(self):
329334
padding="SAME",
330335
expected=expected_output)
331336

337+
@test_util.run_in_graph_and_eager_modes()
332338
def testConv2D2x2FilterStride1x2(self):
333339
expected_output = [58.0, 78.0, 98.0, 118.0, 138.0, 158.0]
334340
self._VerifyValues(
@@ -338,6 +344,7 @@ def testConv2D2x2FilterStride1x2(self):
338344
padding="VALID",
339345
expected=expected_output)
340346

347+
@test_util.run_in_graph_and_eager_modes()
341348
def testConv2DKernelSmallerThanStrideValid(self):
342349
expected_output = [65, 95, 275, 305]
343350
self._VerifyValues(
@@ -347,6 +354,7 @@ def testConv2DKernelSmallerThanStrideValid(self):
347354
padding="VALID",
348355
expected=expected_output)
349356

357+
@test_util.run_in_graph_and_eager_modes()
350358
def testConv2DKernelSmallerThanStrideSame(self):
351359
self._VerifyValues(
352360
tensor_in_sizes=[1, 3, 3, 1],
@@ -369,6 +377,7 @@ def testConv2DKernelSmallerThanStrideSame(self):
369377
padding="SAME",
370378
expected=[44, 28, 41, 16])
371379

380+
@test_util.run_in_graph_and_eager_modes()
372381
def testConv2DKernelSizeMatchesInputSize(self):
373382
self._VerifyValues(
374383
tensor_in_sizes=[1, 2, 2, 1],
@@ -397,7 +406,7 @@ def _RunAndVerifyBackpropInput(self, input_sizes, filter_sizes, output_sizes,
397406
# numbers from 1.
398407
x1 = [f * 1.0 for f in range(1, total_filter_size + 1)]
399408
x2 = [f * 1.0 for f in range(1, total_output_size + 1)]
400-
with self.test_session(use_gpu=use_gpu) as sess:
409+
with test_util.device(use_gpu):
401410
if data_format == "NCHW":
402411
input_sizes = test_util.NHWCToNCHW(input_sizes)
403412
t0 = constant_op.constant(input_sizes, shape=[len(input_sizes)])
@@ -412,7 +421,7 @@ def _RunAndVerifyBackpropInput(self, input_sizes, filter_sizes, output_sizes,
412421
if data_format == "NCHW":
413422
conv = test_util.NCHWToNHWC(conv)
414423
# "values" consists of two tensors for two backprops
415-
value = sess.run(conv)
424+
value = self.evaluate(conv)
416425
self.assertShapeEqual(value, conv)
417426
print("expected = ", expected)
418427
print("actual = ", value)
@@ -424,7 +433,7 @@ def _CompareBackpropInput(self, input_sizes, filter_sizes, output_sizes,
424433
x2 = np.random.rand(*output_sizes).astype(np.float32)
425434

426435
def _GetVal(data_format, use_gpu):
427-
with self.test_session(use_gpu=use_gpu):
436+
with test_util.device(use_gpu):
428437
if data_format == "NCHW":
429438
new_input_sizes = test_util.NHWCToNCHW(input_sizes)
430439
else:
@@ -445,7 +454,7 @@ def _GetVal(data_format, use_gpu):
445454
data_format=data_format)
446455
if data_format == "NCHW":
447456
conv = test_util.NCHWToNHWC(conv)
448-
ret = conv.eval()
457+
ret = self.evaluate(conv)
449458
self.assertShapeEqual(ret, conv)
450459
return ret
451460

@@ -456,6 +465,7 @@ def _GetVal(data_format, use_gpu):
456465
for i in range(1, len(values)):
457466
self.assertAllClose(values[0], values[i], rtol=1e-4, atol=1e-4)
458467

468+
@test_util.run_in_graph_and_eager_modes()
459469
def testConv2D2x2Depth1ValidBackpropInput(self):
460470
expected_output = [1.0, 4.0, 4.0, 3.0, 10.0, 8.0]
461471
for (data_format, use_gpu) in GetTestConfigs():
@@ -470,6 +480,7 @@ def testConv2D2x2Depth1ValidBackpropInput(self):
470480
use_gpu=use_gpu,
471481
err=1e-5)
472482

483+
@test_util.run_in_graph_and_eager_modes()
473484
def testConv2D2x2Depth3ValidBackpropInput(self):
474485
expected_output = [
475486
14.0, 32.0, 50.0, 100.0, 163.0, 226.0, 167.0, 212.0, 257.0, 122.0,
@@ -489,6 +500,7 @@ def testConv2D2x2Depth3ValidBackpropInput(self):
489500
use_gpu=use_gpu,
490501
err=1e-4)
491502

503+
@test_util.run_in_graph_and_eager_modes()
492504
def testConv2D2x2Depth3ValidBackpropInputStride1x2(self):
493505
expected_output = [
494506
1.0, 2.0, 2.0, 4.0, 3.0, 6.0, 7.0, 12.0, 11.0, 18.0, 15.0, 24.0, 12.0,
@@ -506,6 +518,7 @@ def testConv2D2x2Depth3ValidBackpropInputStride1x2(self):
506518
use_gpu=use_gpu,
507519
err=1e-5)
508520

521+
@test_util.run_in_graph_and_eager_modes()
509522
def testConv2DStrideTwoFilterOneSameBackpropInput(self):
510523
expected_output = [
511524
1.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.0, 0.0, 0.0,
@@ -523,6 +536,7 @@ def testConv2DStrideTwoFilterOneSameBackpropInput(self):
523536
use_gpu=use_gpu,
524537
err=1e-5)
525538

539+
@test_util.run_in_graph_and_eager_modes()
526540
def testConv2DKernelSizeMatchesInputSizeBackpropInput(self):
527541
expected_output = [5.0, 11.0, 17.0, 23.0]
528542
for (data_format, use_gpu) in GetTestConfigs():
@@ -552,7 +566,7 @@ def _RunAndVerifyBackpropFilter(self, input_sizes, filter_sizes, output_sizes,
552566
x0 = [f * 1.0 for f in range(1, total_input_size + 1)]
553567
x2 = [f * 1.0 for f in range(1, total_output_size + 1)]
554568
for dtype in self._DtypesToTest(use_gpu=use_gpu):
555-
with self.test_session(use_gpu=use_gpu) as sess:
569+
with test_util.device(use_gpu):
556570
t0 = constant_op.constant(x0, shape=input_sizes, dtype=dtype)
557571
t1 = constant_op.constant(filter_sizes, shape=[len(filter_sizes)])
558572
t2 = constant_op.constant(x2, shape=output_sizes, dtype=dtype)
@@ -568,7 +582,7 @@ def _RunAndVerifyBackpropFilter(self, input_sizes, filter_sizes, output_sizes,
568582
strides=explicit_strides,
569583
padding=padding,
570584
data_format=data_format)
571-
value = sess.run(conv)
585+
value = self.evaluate(conv)
572586
self.assertShapeEqual(value, conv)
573587
print("expected = ", expected)
574588
print("actual = ", value)
@@ -580,7 +594,7 @@ def _CompareBackFilter(self, input_sizes, filter_sizes, output_sizes,
580594
x2 = np.random.rand(*output_sizes).astype(np.float32)
581595

582596
def _GetVal(data_format, use_gpu):
583-
with self.test_session(use_gpu=use_gpu):
597+
with test_util.device(use_gpu):
584598
t0 = constant_op.constant(x0, shape=input_sizes)
585599
t1 = constant_op.constant(filter_sizes, shape=[len(filter_sizes)])
586600
t2 = constant_op.constant(x2, shape=output_sizes)
@@ -596,7 +610,7 @@ def _GetVal(data_format, use_gpu):
596610
strides=strides,
597611
padding=padding,
598612
data_format=data_format)
599-
ret = conv.eval()
613+
ret = self.evaluate(conv)
600614
self.assertShapeEqual(ret, conv)
601615
return ret
602616

@@ -606,6 +620,7 @@ def _GetVal(data_format, use_gpu):
606620
for i in range(1, len(values)):
607621
self.assertAllClose(values[0], values[i], rtol=1e-4, atol=1e-4)
608622

623+
@test_util.run_in_graph_and_eager_modes()
609624
def testConv2D2x2Depth1ValidBackpropFilter(self):
610625
expected = [5.0, 8.0, 14.0, 17.0]
611626
for (data_format, use_gpu) in GetTestConfigs():
@@ -619,6 +634,7 @@ def testConv2D2x2Depth1ValidBackpropFilter(self):
619634
data_format=data_format,
620635
use_gpu=use_gpu)
621636

637+
@test_util.run_in_graph_and_eager_modes()
622638
def testConv2D2x2Depth3ValidBackpropFilter(self):
623639
expected = [
624640
17.0, 22.0, 27.0, 22.0, 29.0, 36.0, 27.0, 36.0, 45.0, 32.0, 43.0, 54.0,
@@ -637,6 +653,7 @@ def testConv2D2x2Depth3ValidBackpropFilter(self):
637653
data_format=data_format,
638654
use_gpu=use_gpu)
639655

656+
@test_util.run_in_graph_and_eager_modes()
640657
def testConv2D2x2Depth3ValidBackpropFilterStride1x2(self):
641658
expected = [161.0, 182.0, 287.0, 308.0]
642659
for (data_format, use_gpu) in GetTestConfigs():
@@ -650,6 +667,7 @@ def testConv2D2x2Depth3ValidBackpropFilterStride1x2(self):
650667
data_format=data_format,
651668
use_gpu=use_gpu)
652669

670+
@test_util.run_in_graph_and_eager_modes()
653671
def testConv2DStrideTwoFilterOneSameBackpropFilter(self):
654672
expected_output = [78.]
655673
for (data_format, use_gpu) in GetTestConfigs():
@@ -663,6 +681,7 @@ def testConv2DStrideTwoFilterOneSameBackpropFilter(self):
663681
data_format=data_format,
664682
use_gpu=use_gpu)
665683

684+
@test_util.run_in_graph_and_eager_modes()
666685
def testConv2DKernelSizeMatchesInputSizeBackpropFilter(self):
667686
expected_output = [1.0, 2.0, 2.0, 4.0, 3.0, 6.0, 4.0, 8.0]
668687
for (data_format, use_gpu) in GetTestConfigs():
@@ -1446,13 +1465,18 @@ def Test(self):
14461465
for index, (input_size_, filter_size_, output_size_, stride_,
14471466
padding_) in enumerate(GetShrunkInceptionShapes()):
14481467
setattr(Conv2DTest, "testInceptionFwd_" + str(index),
1449-
GetInceptionFwdTest(input_size_, filter_size_, stride_, padding_))
1468+
test_util.run_in_graph_and_eager_modes()(
1469+
GetInceptionFwdTest(input_size_, filter_size_, stride_,
1470+
padding_)))
14501471
setattr(Conv2DTest, "testInceptionBackInput_" + str(index),
1451-
GetInceptionBackInputTest(input_size_, filter_size_, output_size_,
1452-
stride_, padding_))
1472+
test_util.run_in_graph_and_eager_modes()(
1473+
GetInceptionBackInputTest(input_size_, filter_size_,
1474+
output_size_, stride_, padding_)))
14531475
setattr(Conv2DTest, "testInceptionBackFilter_" + str(index),
1454-
GetInceptionBackFilterTest(input_size_, filter_size_, output_size_,
1455-
[stride_, stride_], padding_))
1476+
test_util.run_in_graph_and_eager_modes()(
1477+
GetInceptionBackFilterTest(input_size_, filter_size_,
1478+
output_size_, [stride_, stride_],
1479+
padding_)))
14561480

14571481
# TODO(b/35359731)
14581482
# Fwd, BckInput, and BackFilter to test that for certain input parameter
@@ -1464,11 +1488,14 @@ def Test(self):
14641488
fshape = [1, 1, 1, 256]
14651489
oshape = [1, 400, 400, 256]
14661490
setattr(Conv2DTest, "testInceptionFwd_No_Winograd_Nonfused",
1467-
GetInceptionFwdTest(ishape, fshape, 1, "SAME", gpu_only=True))
1491+
test_util.run_in_graph_and_eager_modes()(
1492+
GetInceptionFwdTest(ishape, fshape, 1, "SAME", gpu_only=True)))
14681493
setattr(Conv2DTest, "testInceptionBackInput_No_Winograd_Nonfused",
1469-
GetInceptionBackInputTest(ishape, fshape, oshape, 1, "SAME",
1470-
gpu_only=True))
1494+
test_util.run_in_graph_and_eager_modes()(
1495+
GetInceptionBackInputTest(ishape, fshape, oshape, 1, "SAME",
1496+
gpu_only=True)))
14711497
setattr(Conv2DTest, "testInceptionBackFilter_No_Winograd_Nonfused",
1472-
GetInceptionBackFilterTest(ishape, fshape, oshape, [1, 1], "SAME",
1473-
gpu_only=True))
1498+
test_util.run_in_graph_and_eager_modes()(
1499+
GetInceptionBackFilterTest(ishape, fshape, oshape, [1, 1], "SAME",
1500+
gpu_only=True)))
14741501
test.main()

tensorflow/python/lib/core/py_func.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ Status MakeArgTuple(PyCall* call, PyObject** tuple) {
7979
// module.
8080
Status NumericNpDTypeToTfDType(const int np, DataType* tf) {
8181
switch (np) {
82+
case NPY_FLOAT16:
83+
*tf = DT_HALF;
84+
break;
8285
case NPY_FLOAT32:
8386
*tf = DT_FLOAT;
8487
break;

0 commit comments

Comments
 (0)