Home | History | Annotate | Download | only in framework
      1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 
     16 #include "tensorflow/core/framework/tensor_util.h"
     17 
     18 #include <vector>
     19 #include "tensorflow/core/framework/tensor.h"
     20 #include "tensorflow/core/framework/types.h"
     21 #include "tensorflow/core/lib/core/status_test_util.h"
     22 #include "tensorflow/core/platform/test.h"
     23 
     24 namespace tensorflow {
     25 namespace {
     26 
     27 TEST(TensorUtil, DeepCopy0d) {
     28   Tensor x(DT_FLOAT, TensorShape({}));
     29   x.scalar<float>()() = 10.0;
     30 
     31   // Make y a deep copy of x and then change it.
     32   Tensor y = tensor::DeepCopy(x);
     33   y.scalar<float>()() = 20.0;
     34 
     35   // x doesn't change
     36   EXPECT_EQ(10.0, x.scalar<float>()());
     37 
     38   // Change x.
     39   x.scalar<float>()() = 30.0;
     40 
     41   // Y doesn't change.
     42   EXPECT_EQ(20.0, y.scalar<float>()());
     43 
     44   Tensor z = tensor::DeepCopy(y);
     45 
     46   // Change y.
     47   y.scalar<float>()() = 40.0;
     48 
     49   // The final states should all be different.
     50   EXPECT_EQ(20.0, z.scalar<float>()());
     51   EXPECT_EQ(30.0, x.scalar<float>()());
     52   EXPECT_EQ(40.0, y.scalar<float>()());
     53 
     54   // Should have the same shape and type.
     55   EXPECT_EQ(TensorShape({}), x.shape());
     56   EXPECT_EQ(TensorShape({}), y.shape());
     57   EXPECT_EQ(TensorShape({}), z.shape());
     58 
     59   EXPECT_EQ(DT_FLOAT, x.dtype());
     60   EXPECT_EQ(DT_FLOAT, y.dtype());
     61   EXPECT_EQ(DT_FLOAT, z.dtype());
     62 }
     63 
     64 TEST(TensorUtil, DeepCopyZeroElements) {
     65   Tensor x;
     66   Tensor y = tensor::DeepCopy(x);
     67   EXPECT_EQ(TensorShape({0}), y.shape());
     68   EXPECT_EQ(DT_FLOAT, y.dtype());
     69   EXPECT_EQ(0, y.NumElements());
     70 }
     71 
     72 TEST(TensorUtil, DeepCopy) {
     73   Tensor x(DT_FLOAT, TensorShape({1}));
     74   x.flat<float>()(0) = 10.0;
     75 
     76   // Make y a deep copy of x and then change it.
     77   Tensor y = tensor::DeepCopy(x);
     78   y.flat<float>()(0) = 20.0;
     79 
     80   // x doesn't change
     81   EXPECT_EQ(10.0, x.flat<float>()(0));
     82 
     83   // Change x.
     84   x.flat<float>()(0) = 30.0;
     85 
     86   // Y doesn't change.
     87   EXPECT_EQ(20.0, y.flat<float>()(0));
     88 
     89   Tensor z = tensor::DeepCopy(y);
     90 
     91   // Change y.
     92   y.flat<float>()(0) = 40.0;
     93 
     94   // The final states should all be different.
     95   EXPECT_EQ(20.0, z.flat<float>()(0));
     96   EXPECT_EQ(30.0, x.flat<float>()(0));
     97   EXPECT_EQ(40.0, y.flat<float>()(0));
     98 
     99   // Should have the same shape and type.
    100   EXPECT_EQ(TensorShape({1}), x.shape());
    101   EXPECT_EQ(TensorShape({1}), y.shape());
    102   EXPECT_EQ(TensorShape({1}), z.shape());
    103 
    104   EXPECT_EQ(DT_FLOAT, x.dtype());
    105   EXPECT_EQ(DT_FLOAT, y.dtype());
    106   EXPECT_EQ(DT_FLOAT, z.dtype());
    107 
    108   // Test string deep copy
    109   Tensor str1(DT_STRING, TensorShape({2}));
    110   str1.flat<string>()(0) = "foo1";
    111   str1.flat<string>()(1) = "foo2";
    112   Tensor str2 = tensor::DeepCopy(str1);
    113   str2.flat<string>()(0) = "bar1";
    114   str2.flat<string>()(1) = "bar2";
    115   EXPECT_NE(str2.flat<string>()(0), str1.flat<string>()(0));
    116 }
    117 
    118 TEST(TensorUtil, DeepCopySlice) {
    119   Tensor x(DT_INT32, TensorShape({10}));
    120   x.flat<int32>().setConstant(1);
    121 
    122   // Slice 'x' -- y still refers to the same buffer.
    123   Tensor y = x.Slice(2, 6);
    124 
    125   // Do a deep copy of y, which is a slice.
    126   Tensor z = tensor::DeepCopy(y);
    127 
    128   // Set x to be different.
    129   x.flat<int32>().setConstant(2);
    130 
    131   EXPECT_EQ(TensorShape({10}), x.shape());
    132   EXPECT_EQ(TensorShape({4}), y.shape());
    133   EXPECT_EQ(TensorShape({4}), z.shape());
    134   EXPECT_EQ(DT_INT32, x.dtype());
    135   EXPECT_EQ(DT_INT32, y.dtype());
    136   EXPECT_EQ(DT_INT32, z.dtype());
    137 
    138   // x and y should now all be '2', but z should be '1'.
    139   for (int i = 0; i < 10; ++i) {
    140     EXPECT_EQ(2, x.flat<int32>()(i));
    141   }
    142   for (int i = 0; i < 4; ++i) {
    143     EXPECT_EQ(2, y.unaligned_flat<int32>()(i));
    144     EXPECT_EQ(1, z.flat<int32>()(i));
    145   }
    146 }
    147 
    148 TEST(TensorUtil, Concat) {
    149   std::vector<int64> sizes = {1, 4, 5};
    150   std::vector<Tensor> to_concat;
    151   int64 total_size = 0;
    152   int offset = 0;
    153   for (size_t entry = 0; entry < sizes.size(); ++entry) {
    154     const int64 size = sizes[entry];
    155     Tensor tensor(DT_INT32, TensorShape({size, 2}));
    156     for (int i = offset; i < offset + size; ++i) {
    157       for (int j = 0; j < 2; ++j) {
    158         tensor.matrix<int32>()(i - offset, j) = 2 * i + j;
    159       }
    160     }
    161     to_concat.push_back(tensor);
    162     total_size += size;
    163     offset += size;
    164   }
    165 
    166   Tensor concated;
    167   TF_ASSERT_OK(tensor::Concat(to_concat, &concated));
    168   ASSERT_EQ(TensorShape({total_size, 2}), concated.shape());
    169   for (int i = 0; i < total_size; ++i) {
    170     for (int j = 0; j < 2; ++j) {
    171       EXPECT_EQ(2 * i + j, concated.matrix<int32>()(i, j));
    172     }
    173   }
    174 }
    175 
    176 TEST(TensorUtil, Split) {
    177   Tensor to_split(DT_INT64, TensorShape({10, 2}));
    178   for (int i = 0; i < 10; ++i) {
    179     for (int j = 0; j < 2; ++j) {
    180       to_split.matrix<int64>()(i, j) = 2 * i + j;
    181     }
    182   }
    183 
    184   std::vector<int64> sizes = {1, 4, 5};
    185   std::vector<Tensor> splits;
    186   TF_ASSERT_OK(tensor::Split(to_split, sizes, &splits));
    187   ASSERT_EQ(sizes.size(), splits.size());
    188 
    189   int offset = 0;
    190   for (size_t entry = 0; entry < splits.size(); ++entry) {
    191     const int64 size = sizes[entry];
    192     const Tensor& split = splits[entry];
    193 
    194     ASSERT_EQ(TensorShape({size, 2}), split.shape());
    195     for (int i = offset; i < offset + size; ++i) {
    196       for (int j = 0; j < 2; ++j) {
    197         EXPECT_EQ(2 * i + j, split.matrix<int64>()(i - offset, j));
    198       }
    199     }
    200 
    201     offset += size;
    202   }
    203 }
    204 
    205 TEST(TensorUtil, ConcatSplitStrings) {
    206   Tensor x(DT_STRING, TensorShape({4, 3}));
    207   for (int i = 0; i < 4 * 3; ++i) {
    208     x.flat<string>()(i) = strings::StrCat("foo_", i);
    209   }
    210 
    211   std::vector<Tensor> split;
    212   TF_ASSERT_OK(tensor::Split(x, {2, 1, 1}, &split));
    213   Tensor x_round_tripped;
    214   TF_ASSERT_OK(tensor::Concat(split, &x_round_tripped));
    215   ASSERT_EQ(x.shape(), x_round_tripped.shape());
    216   for (int i = 0; i < 4 * 3; ++i) {
    217     EXPECT_EQ(x.flat<string>()(i), x_round_tripped.flat<string>()(i));
    218   }
    219 
    220   // Ensure that no memory is being shared between 'x' and 'x_round_tripped'.
    221   for (int i = 0; i < 4 * 3; ++i) {
    222     x_round_tripped.flat<string>()(i) = strings::StrCat("bar_", i);
    223   }
    224   for (int i = 0; i < 4 * 3; ++i) {
    225     EXPECT_NE(x.flat<string>()(i), x_round_tripped.flat<string>()(i));
    226   }
    227 }
    228 
    229 }  // namespace
    230 }  // namespace tensorflow
    231