aboutsummaryrefslogtreecommitdiffhomepage
path: root/tensorflow/core/kernels/tensor_array.cc
diff options
context:
space:
mode:
authorGravatar Eugene Brevdo <ebrevdo@gmail.com>2016-04-08 12:34:56 -0800
committerGravatar TensorFlower Gardener <gardener@tensorflow.org>2016-04-08 13:41:41 -0700
commit2d691fe77da04492146b65f6d700bdf843902e4a (patch)
treeaa563987d906c736647db672ccd407ebe26bea2e /tensorflow/core/kernels/tensor_array.cc
parent55810fa85b7c48efa8a6a824736014e594d6aed1 (diff)
Re-enable write-once, read-many semantics for TensorArray.
This implementation is a bit more efficient than the previous one because the first write just performs a shallow copy. Only on an aggregation is any new memory allocated. For read-many semantics, the operations read, pack, and concat must be called with parameter clear_after_read=False. By default, the flag is set True; this means a read will remove the reference to the underlying Tensor in the TensorArray to reclaim memory in the runtime. Change: 119404140
Diffstat (limited to 'tensorflow/core/kernels/tensor_array.cc')
-rw-r--r--tensorflow/core/kernels/tensor_array.cc89
1 files changed, 45 insertions, 44 deletions
diff --git a/tensorflow/core/kernels/tensor_array.cc b/tensorflow/core/kernels/tensor_array.cc
index f9267a902a..3dab15f780 100644
--- a/tensorflow/core/kernels/tensor_array.cc
+++ b/tensorflow/core/kernels/tensor_array.cc
@@ -13,49 +13,45 @@ See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
+#define EIGEN_USE_THREADS
#include "tensorflow/core/kernels/tensor_array.h"
+#include "third_party/eigen3/unsupported/Eigen/CXX11/Tensor"
+#include "tensorflow/core/framework/register_types.h"
+#include "tensorflow/core/kernels/aggregate_ops_cpu.h"
+
namespace tensorflow {
-Status TensorArray::LockedWrite(OpKernelContext* ctx, const int32 index,
- PersistentTensor* value) {
- TF_RETURN_IF_ERROR(LockedReturnIfClosed());
- size_t index_size = static_cast<size_t>(index);
- if (index < 0 ||
- (!dynamic_size_ && index_size >= tensors_.size())) {
- return errors::InvalidArgument(
- "TensorArray ", handle_.vec<string>()(1), ": Tried to write to index ",
- index, " but array is not resizeable and size is: ", tensors_.size());
- }
- if (dynamic_size_) {
- // We must grow the internal TensorArray
- if (index_size >= tensors_.capacity()) {
- tensors_.reserve(2 * (index_size + 1));
- }
- if (index_size >= tensors_.size()) {
- tensors_.resize(index_size + 1);
- }
- }
- TensorAndState& t = tensors_[index];
- if (t.written) {
- return errors::InvalidArgument("TensorArray ", handle_.vec<string>()(1),
- ": Could not write to TensorArray index ",
- index,
- " because it has already been written to.");
- }
- Tensor* value_t = value->AccessTensor(ctx);
- if (value_t->dtype() != dtype_) {
- return errors::InvalidArgument(
- "TensorArray ", handle_.vec<string>()(1),
- ": Could not write to TensorArray index ", index,
- " because the value dtype is ", DataTypeString(value_t->dtype()),
- " but TensorArray dtype is ", DataTypeString(dtype_), ".");
+typedef Eigen::ThreadPoolDevice CPUDevice;
+typedef Eigen::GpuDevice GPUDevice;
+
+namespace tensor_array {
+
+#define TENSOR_ARRAY_WRITE_OR_ADD(Device, T) \
+ template <> \
+ Status AddToTensor<Device, T>(OpKernelContext * ctx, Tensor * sum, \
+ const Tensor* current, const Tensor* add) { \
+ functor::Add2Functor<Device, T> add_functor; \
+ add_functor(ctx->template eigen_device<Device>(), sum->flat<T>(), \
+ current->flat<T>(), add->flat<T>()); \
+ return Status::OK(); \
}
- t.tensor = *value;
- t.shape = value_t->shape();
- t.written = true;
- return Status::OK();
-}
+
+#define TENSOR_ARRAY_WRITE_OR_ADD_CPU(T) TENSOR_ARRAY_WRITE_OR_ADD(CPUDevice, T)
+TF_CALL_NUMBER_TYPES(TENSOR_ARRAY_WRITE_OR_ADD_CPU)
+#undef TENSOR_ARRAY_WRITE_OR_ADD_CPU
+
+#if GOOGLE_CUDA
+
+#define TENSOR_ARRAY_WRITE_OR_ADD_GPU(T) TENSOR_ARRAY_WRITE_OR_ADD(GPUDevice, T)
+TF_CALL_GPU_NUMBER_TYPES(TENSOR_ARRAY_WRITE_OR_ADD_GPU);
+#undef TENSOR_ARRAY_WRITE_OR_ADD_GPU
+
+#endif // GOOGLE_CUDA
+
+#undef TENSOR_ARRAY_WRITE_OR_ADD
+
+} // namespace tensor_array
Status TensorArray::LockedRead(const int32 index, PersistentTensor* value) {
TF_RETURN_IF_ERROR(LockedReturnIfClosed());
@@ -64,20 +60,25 @@ Status TensorArray::LockedRead(const int32 index, PersistentTensor* value) {
" but array size is: ", tensors_.size());
}
TensorAndState& t = tensors_[index];
- if (t.read) {
- return errors::InvalidArgument(
- "TensorArray ", handle_.vec<string>()(1), ": Could not read index ",
- index, " twice because TensorArray a read-once object.");
- }
if (!t.written) {
return errors::InvalidArgument("TensorArray ", handle_.vec<string>()(1),
": Could not read from TensorArray index ",
index,
" because it has not yet been written to.");
}
+ if (t.cleared) {
+ return errors::InvalidArgument("TensorArray ", handle_.vec<string>()(1),
+ ": Could not read index ", index,
+ " twice because it was cleared after a "
+ "previous read (perhaps try setting "
+ "clear_after_read = false?).");
+ }
*value = t.tensor;
+ if (clear_after_read_) {
+ t.tensor = PersistentTensor();
+ t.cleared = true;
+ }
t.read = true;
- t.tensor = PersistentTensor();
return Status::OK();
}