Fixes a reentrant lock issue with tensors using ndarray memory which uses tensor memory.

PiperOrigin-RevId: 161137788
This commit is contained in:
Alexandre Passos 2017-07-06 15:15:45 -07:00 committed by TensorFlower Gardener
parent a2ee8bca3f
commit 68d6667370
2 changed files with 25 additions and 6 deletions

View File

@ -113,8 +113,8 @@ class PyOpTest(test.TestCase):
# returns a tuple, Tout and inp a tuple # returns a tuple, Tout and inp a tuple
with self.test_session(): with self.test_session():
x = constant_op.constant(0.0, dtypes.float64) x = constant_op.constant(0.0, dtypes.float64)
y, z = script_ops.py_func(tuple_func, (x,), y, z = script_ops.py_func(tuple_func, (x,), (dtypes.float64,
(dtypes.float64, dtypes.float64)) dtypes.float64))
self.assertAllClose(y.eval(), 0.0) self.assertAllClose(y.eval(), 0.0)
self.assertAllClose(z.eval(), 1.0) self.assertAllClose(z.eval(), 1.0)
@ -194,6 +194,21 @@ class PyOpTest(test.TestCase):
"Unsupported object type"): "Unsupported object type"):
z.eval() z.eval()
def testReturnInput(self):
with self.test_session():
def ident(x):
return x[0]
p = array_ops.placeholder(dtypes.float32)
# Create a numpy array aliasing a tensor and a tensor aliasing this array
z, = script_ops.py_func(ident, [p], [dtypes.float32])
z += 0.0 # Makes sure we release the tensor aliasing the numpy array x[0]
# above instead of using its memory as the return value of
# session.run
self.assertEqual(0.0, z.eval(feed_dict={p: [0.0]}))
def testStateful(self): def testStateful(self):
# Not using self.test_session(), which disables optimization. # Not using self.test_session(), which disables optimization.
with session_lib.Session() as sess: with session_lib.Session() as sess:
@ -225,7 +240,8 @@ class PyOpTest(test.TestCase):
def testCOrder(self): def testCOrder(self):
with self.test_session(): with self.test_session():
val = [[1, 2], [3, 4]] val = [[1, 2], [3, 4]]
x, = script_ops.py_func(lambda: np.array(val, order="F"), [], [dtypes.int64]) x, = script_ops.py_func(lambda: np.array(val, order="F"), [],
[dtypes.int64])
self.assertAllEqual(val, x.eval()) self.assertAllEqual(val, x.eval())
def testParallel(self): def testParallel(self):

View File

@ -49,11 +49,14 @@ void DelayedNumpyDecref(void* data, size_t len, void* obj) {
// Actually dereferences cached numpy arrays. REQUIRES being called while // Actually dereferences cached numpy arrays. REQUIRES being called while
// holding the GIL. // holding the GIL.
void ClearDecrefCache() { void ClearDecrefCache() {
mutex_lock ml(*DelayedDecrefLock()); std::vector<void*> cache_copy;
for (void* obj : *DecrefCache()) { {
mutex_lock ml(*DelayedDecrefLock());
cache_copy.swap(*DecrefCache());
}
for (void* obj : cache_copy) {
Py_DECREF(reinterpret_cast<PyObject*>(obj)); Py_DECREF(reinterpret_cast<PyObject*>(obj));
} }
DecrefCache()->clear();
} }
// Structure which keeps a reference to a Tensor alive while numpy has a pointer // Structure which keeps a reference to a Tensor alive while numpy has a pointer