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