blob: 2358d65918ebf05d7d35f29cdd4fd9e78b1989ab [file] [log] [blame]
Richard Burtondc0c6ed2020-04-08 16:39:05 +01001# Copyright © 2020 Arm Ltd. All rights reserved.
2# SPDX-License-Identifier: MIT
3import pytest
4import numpy as np
5
6import pyarmnn as ann
7
8
Cathal Corbett5b8093c2021-10-22 11:12:07 +01009def _get_const_tensor_info(dt):
10 tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), dt, 0.0, 0, True)
Richard Burtondc0c6ed2020-04-08 16:39:05 +010011
12 return tensor_info
13
14
15@pytest.mark.parametrize("dt, data",
16 [
17 (ann.DataType_Float32, np.random.randint(1, size=(2, 4)).astype(np.float32)),
18 (ann.DataType_Float16, np.random.randint(1, size=(2, 4)).astype(np.float16)),
19 (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 4)).astype(np.uint8)),
20 (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 4)).astype(np.int8)),
21 (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 4)).astype(np.int8)),
22 (ann.DataType_Signed32, np.random.randint(1, size=(2, 4)).astype(np.int32)),
23 (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 4)).astype(np.int16))
24 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
25def test_const_tensor_too_many_elements(dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +010026 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +010027 num_bytes = tensor_info.GetNumBytes()
28
29 with pytest.raises(ValueError) as err:
30 ann.ConstTensor(tensor_info, data)
31
32 assert 'ConstTensor requires {} bytes, {} provided.'.format(num_bytes, data.nbytes) in str(err.value)
33
34
35@pytest.mark.parametrize("dt, data",
36 [
37 (ann.DataType_Float32, np.random.randint(1, size=(2, 2)).astype(np.float32)),
38 (ann.DataType_Float16, np.random.randint(1, size=(2, 2)).astype(np.float16)),
39 (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 2)).astype(np.uint8)),
40 (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 2)).astype(np.int8)),
41 (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 2)).astype(np.int8)),
42 (ann.DataType_Signed32, np.random.randint(1, size=(2, 2)).astype(np.int32)),
43 (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 2)).astype(np.int16))
44 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
45def test_const_tensor_too_little_elements(dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +010046 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +010047 num_bytes = tensor_info.GetNumBytes()
48
49 with pytest.raises(ValueError) as err:
50 ann.ConstTensor(tensor_info, data)
51
52 assert 'ConstTensor requires {} bytes, {} provided.'.format(num_bytes, data.nbytes) in str(err.value)
53
54
55@pytest.mark.parametrize("dt, data",
56 [
57 (ann.DataType_Float32, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.float32)),
58 (ann.DataType_Float16, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.float16)),
59 (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.uint8)),
60 (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.int8)),
61 (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.int8)),
62 (ann.DataType_Signed32, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.int32)),
63 (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 2, 3, 3)).astype(np.int16))
64 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
65def test_const_tensor_multi_dimensional_input(dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +010066 tensor = ann.ConstTensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt, 0.0, 0, True), data)
Richard Burtondc0c6ed2020-04-08 16:39:05 +010067
68 assert data.size == tensor.GetNumElements()
69 assert data.nbytes == tensor.GetNumBytes()
70 assert dt == tensor.GetDataType()
71 assert tensor.get_memory_area().data
72
73
74def test_create_const_tensor_from_tensor():
Cathal Corbett5b8093c2021-10-22 11:12:07 +010075 tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_Float32, 0.0, 0, True)
Richard Burtondc0c6ed2020-04-08 16:39:05 +010076 tensor = ann.Tensor(tensor_info)
77 copied_tensor = ann.ConstTensor(tensor)
78
79 assert copied_tensor != tensor, "Different objects"
80 assert copied_tensor.GetInfo() != tensor.GetInfo(), "Different objects"
81 assert copied_tensor.get_memory_area().ctypes.data == tensor.get_memory_area().ctypes.data, "Same memory area"
82 assert copied_tensor.GetNumElements() == tensor.GetNumElements()
83 assert copied_tensor.GetNumBytes() == tensor.GetNumBytes()
84 assert copied_tensor.GetDataType() == tensor.GetDataType()
85
86
87def test_const_tensor_from_tensor_has_memory_area_access_after_deletion_of_original_tensor():
Cathal Corbett5b8093c2021-10-22 11:12:07 +010088 tensor_info = ann.TensorInfo(ann.TensorShape((2, 3)), ann.DataType_Float32, 0.0, 0, True)
Richard Burtondc0c6ed2020-04-08 16:39:05 +010089 tensor = ann.Tensor(tensor_info)
90
91 tensor.get_memory_area()[0] = 100
92
93 copied_mem = tensor.get_memory_area().copy()
94
95 assert 100 == copied_mem[0], "Memory was copied correctly"
96
97 copied_tensor = ann.ConstTensor(tensor)
98
99 tensor.get_memory_area()[0] = 200
100
101 assert 200 == tensor.get_memory_area()[0], "Tensor and copied Tensor point to the same memory"
102 assert 200 == copied_tensor.get_memory_area()[0], "Tensor and copied Tensor point to the same memory"
103
104 assert 100 == copied_mem[0], "Copied test memory not affected"
105
106 copied_mem[0] = 200 # modify test memory to equal copied Tensor
107
108 del tensor
109 np.testing.assert_array_equal(copied_tensor.get_memory_area(), copied_mem), "After initial tensor was deleted, " \
110 "copied Tensor still has " \
111 "its memory as expected"
112
113
114def test_create_const_tensor_incorrect_args():
115 with pytest.raises(ValueError) as err:
116 ann.ConstTensor('something', 'something')
117
118 expected_error_message = "Incorrect number of arguments or type of arguments provided to create Const Tensor."
119 assert expected_error_message in str(err.value)
120
121
122@pytest.mark.parametrize("dt, data",
123 [
124 # -1 not in data type enum
125 (-1, np.random.randint(1, size=(2, 3)).astype(np.float32)),
126 ], ids=['unknown'])
127def test_const_tensor_unsupported_datatype(dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100128 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100129
130 with pytest.raises(ValueError) as err:
131 ann.ConstTensor(tensor_info, data)
132
133 assert 'The data type provided for this Tensor is not supported: -1' in str(err.value)
134
135
136@pytest.mark.parametrize("dt, data",
137 [
138 (ann.DataType_Float32, [[1, 1, 1], [1, 1, 1]]),
139 (ann.DataType_Float16, [[1, 1, 1], [1, 1, 1]]),
140 (ann.DataType_QAsymmU8, [[1, 1, 1], [1, 1, 1]]),
141 (ann.DataType_QAsymmS8, [[1, 1, 1], [1, 1, 1]]),
142 (ann.DataType_QSymmS8, [[1, 1, 1], [1, 1, 1]])
143 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8'])
144def test_const_tensor_incorrect_input_datatype(dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100145 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100146
147 with pytest.raises(TypeError) as err:
148 ann.ConstTensor(tensor_info, data)
149
150 assert 'Data must be provided as a numpy array.' in str(err.value)
151
152
153@pytest.mark.parametrize("dt, data",
154 [
155 (ann.DataType_Float32, np.random.randint(1, size=(2, 3)).astype(np.float32)),
156 (ann.DataType_Float16, np.random.randint(1, size=(2, 3)).astype(np.float16)),
157 (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 3)).astype(np.uint8)),
158 (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
159 (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
160 (ann.DataType_Signed32, np.random.randint(1, size=(2, 3)).astype(np.int32)),
161 (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 3)).astype(np.int16))
162 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
163class TestNumpyDataTypes:
164
165 def test_copy_const_tensor(self, dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100166 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100167 tensor = ann.ConstTensor(tensor_info, data)
168 copied_tensor = ann.ConstTensor(tensor)
169
170 assert copied_tensor != tensor, "Different objects"
171 assert copied_tensor.GetInfo() != tensor.GetInfo(), "Different objects"
172 assert copied_tensor.get_memory_area().ctypes.data == tensor.get_memory_area().ctypes.data, "Same memory area"
173 assert copied_tensor.GetNumElements() == tensor.GetNumElements()
174 assert copied_tensor.GetNumBytes() == tensor.GetNumBytes()
175 assert copied_tensor.GetDataType() == tensor.GetDataType()
176
177 def test_const_tensor__str__(self, dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100178 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100179 d_type = tensor_info.GetDataType()
180 num_dimensions = tensor_info.GetNumDimensions()
181 num_bytes = tensor_info.GetNumBytes()
182 num_elements = tensor_info.GetNumElements()
183 tensor = ann.ConstTensor(tensor_info, data)
184
185 assert str(tensor) == "ConstTensor{{DataType: {}, NumBytes: {}, NumDimensions: " \
186 "{}, NumElements: {}}}".format(d_type, num_bytes, num_dimensions, num_elements)
187
188 def test_const_tensor_with_info(self, dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100189 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100190 elements = tensor_info.GetNumElements()
191 num_bytes = tensor_info.GetNumBytes()
192 d_type = dt
193
194 tensor = ann.ConstTensor(tensor_info, data)
195
196 assert tensor_info != tensor.GetInfo(), "Different objects"
197 assert elements == tensor.GetNumElements()
198 assert num_bytes == tensor.GetNumBytes()
199 assert d_type == tensor.GetDataType()
200
201 def test_immutable_memory(self, dt, data):
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100202 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100203
204 tensor = ann.ConstTensor(tensor_info, data)
205
206 with pytest.raises(ValueError) as err:
207 tensor.get_memory_area()[0] = 0
208
209 assert 'is read-only' in str(err.value)
210
211 def test_numpy_dtype_matches_ann_dtype(self, dt, data):
212 np_data_type_mapping = {ann.DataType_QAsymmU8: np.uint8,
213 ann.DataType_QAsymmS8: np.int8,
214 ann.DataType_QSymmS8: np.int8,
215 ann.DataType_Float32: np.float32,
216 ann.DataType_QSymmS16: np.int16,
217 ann.DataType_Signed32: np.int32,
218 ann.DataType_Float16: np.float16}
219
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100220 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100221 tensor = ann.ConstTensor(tensor_info, data)
222 assert np_data_type_mapping[tensor.GetDataType()] == data.dtype
223
224
225# This test checks that mismatched numpy and PyArmNN datatypes with same number of bits raises correct error.
226@pytest.mark.parametrize("dt, data",
227 [
228 (ann.DataType_Float32, np.random.randint(1, size=(2, 3)).astype(np.int32)),
229 (ann.DataType_Float16, np.random.randint(1, size=(2, 3)).astype(np.int16)),
230 (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
231 (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 3)).astype(np.uint8)),
232 (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 3)).astype(np.uint8)),
233 (ann.DataType_Signed32, np.random.randint(1, size=(2, 3)).astype(np.float32)),
234 (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 3)).astype(np.float16))
235 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
236def test_numpy_dtype_mismatch_ann_dtype(dt, data):
237 np_data_type_mapping = {ann.DataType_QAsymmU8: np.uint8,
238 ann.DataType_QAsymmS8: np.int8,
239 ann.DataType_QSymmS8: np.int8,
240 ann.DataType_Float32: np.float32,
241 ann.DataType_QSymmS16: np.int16,
242 ann.DataType_Signed32: np.int32,
243 ann.DataType_Float16: np.float16}
244
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100245 tensor_info = _get_const_tensor_info(dt)
Richard Burtondc0c6ed2020-04-08 16:39:05 +0100246 with pytest.raises(TypeError) as err:
247 ann.ConstTensor(tensor_info, data)
248
249 assert str(err.value) == "Expected data to have type {} for type {} but instead got numpy.{}".format(
250 np_data_type_mapping[dt], dt, data.dtype)
251
Cathal Corbett5b8093c2021-10-22 11:12:07 +0100252
253@pytest.mark.parametrize("dt, data",
254 [
255 (ann.DataType_Float32, np.random.randint(1, size=(2, 3)).astype(np.float32)),
256 (ann.DataType_Float16, np.random.randint(1, size=(2, 3)).astype(np.float16)),
257 (ann.DataType_QAsymmU8, np.random.randint(1, size=(2, 3)).astype(np.uint8)),
258 (ann.DataType_QAsymmS8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
259 (ann.DataType_QSymmS8, np.random.randint(1, size=(2, 3)).astype(np.int8)),
260 (ann.DataType_Signed32, np.random.randint(1, size=(2, 3)).astype(np.int32)),
261 (ann.DataType_QSymmS16, np.random.randint(1, size=(2, 3)).astype(np.int16))
262 ], ids=['float32', 'float16', 'unsigned int8', 'signed int8', 'signed int8', 'int32', 'int16'])
263class TestConstTensorConstructorErrors:
264
265 def test_tensorinfo_isconstant_not_set(self, dt, data):
266 with pytest.raises(ValueError) as err:
267 ann.ConstTensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt, 0.0, 0, False), data)
268
269 assert str(err.value) == "TensorInfo when initializing ConstTensor must be set to constant."
270
271 def test_tensor_tensorinfo_isconstant_not_set(self, dt, data):
272 with pytest.raises(ValueError) as err:
273 ann.ConstTensor(ann.Tensor(ann.TensorInfo(ann.TensorShape((2, 2, 3, 3)), dt, 0.0, 0, False), data))
274
275 assert str(err.value) == "TensorInfo of Tensor when initializing ConstTensor must be set to constant."