1 #include <gtest/gtest.h> 3 #include <torch/types.h> 13 return left.item<
T>() == right;
17 bool almost_equal(
at::Tensor left,
T right,
T tolerance = 1e-4) {
18 return std::abs(left.item<
T>() - right) < tolerance;
21 #define REQUIRE_TENSOR_OPTIONS(device_, index_, type_, layout_) \ 23 tensor.device().type() == at::Device((device_), (index_)).type()); \ 25 tensor.device().index() == at::Device((device_), (index_)).index()); \ 26 ASSERT_EQ(tensor.dtype(), (type_)); \ 27 ASSERT_TRUE(tensor.layout() == (layout_)) 29 TEST(TensorTest, ToDtype) {
30 auto tensor = at::empty({3, 4});
31 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kFloat, at::kStrided);
33 tensor = tensor.to(at::kInt);
34 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kInt, at::kStrided);
36 tensor = tensor.to(at::kChar);
37 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kChar, at::kStrided);
39 tensor = tensor.to(at::kDouble);
40 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kDouble, at::kStrided);
43 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kInt, at::kStrided);
46 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kChar, at::kStrided);
49 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kDouble, at::kStrided);
52 TEST(TensorTest, ToTensorAndTensorAttributes) {
53 auto tensor = at::empty({3, 4});
54 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kFloat, at::kStrided);
56 auto other = at::empty({3, 4}, at::kInt);
57 tensor = tensor.to(other);
58 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kInt, at::kStrided);
60 other = at::empty({3, 4}, at::kDouble);
61 tensor = tensor.to(other.dtype());
62 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kDouble, at::kStrided);
63 tensor = tensor.to(other.device());
64 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kDouble, at::kStrided);
66 other = at::empty({3, 4}, at::kLong);
67 tensor = tensor.to(other.device(), other.dtype());
68 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kLong, at::kStrided);
70 other = at::empty({3, 4}, at::kInt);
71 tensor = tensor.to(other.options());
72 REQUIRE_TENSOR_OPTIONS(at::kCPU, -1, at::kInt, at::kStrided);
87 TEST(TensorTest, ToOptionsWithRequiresGrad) {
90 auto tensor = torch::empty({3, 4}, at::requires_grad());
91 ASSERT_TRUE(tensor.requires_grad());
93 tensor = tensor.to(at::kDouble);
94 ASSERT_TRUE(tensor.requires_grad());
103 auto tensor = torch::empty({3, 4});
104 ASSERT_FALSE(tensor.requires_grad());
107 tensor = tensor.to(at::kDouble);
108 ASSERT_FALSE(tensor.requires_grad());
118 TEST(TensorTest, ToDoesNotCopyWhenOptionsAreAllTheSame) {
120 auto tensor = at::empty({3, 4}, at::kFloat);
121 auto hopefully_not_copy = tensor.to(at::kFloat);
122 ASSERT_EQ(hopefully_not_copy.data<
float>(), tensor.data<
float>());
125 auto tensor = at::empty({3, 4}, at::kFloat);
126 auto hopefully_not_copy = tensor.to(tensor.options());
127 ASSERT_EQ(hopefully_not_copy.data<
float>(), tensor.data<
float>());
130 auto tensor = at::empty({3, 4}, at::kFloat);
131 auto hopefully_not_copy = tensor.to(tensor.dtype());
132 ASSERT_EQ(hopefully_not_copy.data<
float>(), tensor.data<
float>());
135 auto tensor = at::empty({3, 4}, at::kFloat);
136 auto hopefully_not_copy = tensor.to(tensor.device());
137 ASSERT_EQ(hopefully_not_copy.data<
float>(), tensor.data<
float>());
140 auto tensor = at::empty({3, 4}, at::kFloat);
141 auto hopefully_not_copy = tensor.to(tensor);
142 ASSERT_EQ(hopefully_not_copy.data<
float>(), tensor.data<
float>());
146 TEST(TensorTest, ContainsCorrectValueForSingleValue) {
147 auto tensor = at::tensor(123);
148 ASSERT_EQ(tensor.numel(), 1);
149 ASSERT_EQ(tensor.dtype(), at::kInt);
150 ASSERT_EQ(tensor[0].item<int32_t>(), 123);
152 tensor = at::tensor(123.456f);
153 ASSERT_EQ(tensor.numel(), 1);
154 ASSERT_EQ(tensor.dtype(), at::kFloat);
155 ASSERT_TRUE(almost_equal(tensor[0], 123.456f));
157 tensor = at::tensor(123.456);
158 ASSERT_EQ(tensor.numel(), 1);
159 ASSERT_EQ(tensor.dtype(), at::kDouble);
160 ASSERT_TRUE(almost_equal(tensor[0], 123.456));
163 TEST(TensorTest, ContainsCorrectValuesForManyValues) {
164 auto tensor = at::tensor({1, 2, 3});
165 ASSERT_EQ(tensor.numel(), 3);
166 ASSERT_EQ(tensor.dtype(), at::kInt);
167 ASSERT_TRUE(exactly_equal(tensor[0], 1));
168 ASSERT_TRUE(exactly_equal(tensor[1], 2));
169 ASSERT_TRUE(exactly_equal(tensor[2], 3));
171 tensor = at::tensor({1.5, 2.25, 3.125});
172 ASSERT_EQ(tensor.numel(), 3);
173 ASSERT_EQ(tensor.dtype(), at::kDouble);
174 ASSERT_TRUE(almost_equal(tensor[0], 1.5));
175 ASSERT_TRUE(almost_equal(tensor[1], 2.25));
176 ASSERT_TRUE(almost_equal(tensor[2], 3.125));
179 TEST(TensorTest, ContainsCorrectValuesForManyValuesVariable) {
180 auto tensor = torch::tensor({1, 2, 3});
181 ASSERT_TRUE(tensor.is_variable());
182 ASSERT_EQ(tensor.numel(), 3);
183 ASSERT_EQ(tensor.dtype(), at::kInt);
184 ASSERT_TRUE(exactly_equal(tensor[0], 1));
185 ASSERT_TRUE(exactly_equal(tensor[1], 2));
186 ASSERT_TRUE(exactly_equal(tensor[2], 3));
188 tensor = torch::tensor({1.5, 2.25, 3.125});
189 ASSERT_TRUE(tensor.is_variable());
190 ASSERT_EQ(tensor.numel(), 3);
191 ASSERT_EQ(tensor.dtype(), at::kDouble);
192 ASSERT_TRUE(almost_equal(tensor[0], 1.5));
193 ASSERT_TRUE(almost_equal(tensor[1], 2.25));
194 ASSERT_TRUE(almost_equal(tensor[2], 3.125));
197 TEST(TensorTest, ContainsCorrectValuesWhenConstructedFromVector) {
198 std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
199 auto tensor = at::tensor(v);
200 ASSERT_EQ(tensor.numel(), v.size());
201 ASSERT_EQ(tensor.dtype(), at::kInt);
202 for (
size_t i = 0; i < v.size(); ++i) {
203 ASSERT_TRUE(exactly_equal(tensor[i], v.at(i)));
206 std::vector<double> w = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.0};
207 tensor = at::tensor(w);
208 ASSERT_EQ(tensor.numel(), w.size());
209 ASSERT_EQ(tensor.dtype(), at::kDouble);
210 for (
size_t i = 0; i < w.size(); ++i) {
211 ASSERT_TRUE(almost_equal(tensor[i], w.at(i)));
215 TEST(TensorTest, UsesOptionsThatAreSupplied) {
216 auto tensor = at::tensor(123, at::dtype(at::kFloat)) + 0.5;
217 ASSERT_EQ(tensor.numel(), 1);
218 ASSERT_EQ(tensor.dtype(), at::kFloat);
219 ASSERT_TRUE(almost_equal(tensor[0], 123.5));
221 tensor = at::tensor({1.1, 2.2, 3.3}, at::dtype(at::kInt));
222 ASSERT_EQ(tensor.numel(), 3);
223 ASSERT_EQ(tensor.dtype(), at::kInt);
224 ASSERT_EQ(tensor.layout(), at::kStrided);
225 ASSERT_TRUE(exactly_equal(tensor[0], 1));
226 ASSERT_TRUE(exactly_equal(tensor[1], 2));
227 ASSERT_TRUE(exactly_equal(tensor[2], 3));
230 TEST(TensorTest, FromBlob) {
231 std::vector<double> v = {1.0, 2.0, 3.0};
232 auto tensor = torch::from_blob(
233 v.data(), v.size(), torch::dtype(torch::kFloat64).requires_grad(
true));
234 ASSERT_TRUE(tensor.is_variable());
235 ASSERT_TRUE(tensor.requires_grad());
236 ASSERT_EQ(tensor.dtype(), torch::kFloat64);
237 ASSERT_EQ(tensor.numel(), 3);
238 ASSERT_EQ(tensor[0].item<double>(), 1);
239 ASSERT_EQ(tensor[1].item<double>(), 2);
240 ASSERT_EQ(tensor[2].item<double>(), 3);
243 TEST(TensorTest, FromBlobUsesDeleter) {
246 std::vector<int32_t> v = {1, 2, 3};
247 auto tensor = torch::from_blob(
250 [&called](
void* data) { called =
true; },
256 TEST(TensorTest, FromBlobWithStrides) {
258 std::vector<int32_t> v = {
264 auto tensor = torch::from_blob(
269 ASSERT_TRUE(tensor.is_variable());
270 ASSERT_EQ(tensor.dtype(), torch::kInt32);
271 ASSERT_EQ(tensor.numel(), 9);
272 const std::vector<int64_t> expected_strides = {1, 3};
273 ASSERT_EQ(tensor.strides(), expected_strides);
274 for (int64_t i = 0; i < tensor.size(0); ++i) {
275 for (int64_t j = 0; j < tensor.size(1); ++j) {
277 EXPECT_EQ(tensor[i][j].item<int32_t>(), 1 + (j * tensor.size(1)) + i);
282 TEST(TensorTest, Item) {
286 ASSERT_NEAR(scalar.to<
float>(), 3.14, 1e-5);
291 ASSERT_EQ(scalar.to<
int>(), 123);
295 TEST(TensorTest, Item_CUDA) {
299 ASSERT_NEAR(scalar.to<
float>(), 3.14, 1e-5);
304 ASSERT_EQ(scalar.to<
int>(), 123);
Scalar represents a 0-dimensional tensor which contains a single element.
The primary ATen error class.
C10_NODISCARD TensorOptions requires_grad(c10::optional< bool > requires_grad) const noexcept
Sets the requires_grad property of the TensorOptions.