blob: 1a5bcd4fbba6b063315e887a829ab9f7d5482b22 [file] [log] [blame]
telsoa014fcda012018-03-09 14:13:49 +00001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beckecb56cd2018-09-05 12:52:57 +01003// SPDX-License-Identifier: MIT
telsoa014fcda012018-03-09 14:13:49 +00004//
5#pragma once
6
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +00007#include "ActivationFixture.hpp"
8#include "QuantizeHelper.hpp"
9
telsoa014fcda012018-03-09 14:13:49 +000010#include <armnn/ArmNN.hpp>
11#include <armnn/Tensor.hpp>
12#include <armnn/TypesUtils.hpp>
telsoa014fcda012018-03-09 14:13:49 +000013
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000014#include <backendsCommon/CpuTensorHandle.hpp>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000015#include <backendsCommon/IBackendInternal.hpp>
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000016#include <backendsCommon/WorkloadFactory.hpp>
telsoa014fcda012018-03-09 14:13:49 +000017
Aron Virginas-Tarc9cc8042018-11-01 16:15:57 +000018#include <test/TensorHelpers.hpp>
telsoa014fcda012018-03-09 14:13:49 +000019
20#include <algorithm>
21
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +000022template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000023LayerTestResult<T, 4> BoundedReLuTestCommon(
24 armnn::IWorkloadFactory& workloadFactory,
25 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
26 float upperBound,
27 float lowerBound,
28 float inputScale,
29 int32_t inputOffset,
30 float outputScale,
31 int32_t outputOffset,
32 const std::vector<T>& inputData,
33 const std::vector<T>& outputExpectedData,
34 unsigned int inputWidth,
35 unsigned int inputHeight,
36 unsigned int inputChannels,
37 unsigned int inputBatchSize)
telsoa014fcda012018-03-09 14:13:49 +000038{
39 unsigned int outputWidth = inputWidth;
40 unsigned int outputHeight = inputHeight;
41 unsigned int outputChannels = inputChannels;
42 unsigned int outputBatchSize = inputBatchSize;
43
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +000044 armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +000045
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +000046 armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +000047
48 if(armnn::IsQuantizedType<T>())
49 {
50 inputTensorInfo.SetQuantizationScale(inputScale);
51 inputTensorInfo.SetQuantizationOffset(inputOffset);
52
53 outputTensorInfo.SetQuantizationScale(outputScale);
54 outputTensorInfo.SetQuantizationOffset(outputOffset);
55 }
56
57 LayerTestResult<T, 4> result(inputTensorInfo);
58
59 auto input = MakeTensor<T, 4>(inputTensorInfo, inputData);
60
61 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
62 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
63
telsoa01c577f2c2018-08-31 09:22:23 +010064 // Setup bounded ReLu.
telsoa014fcda012018-03-09 14:13:49 +000065 armnn::ActivationQueueDescriptor descriptor;
66 armnn::WorkloadInfo workloadInfo;
67 AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
68 AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
69
70 descriptor.m_Parameters.m_Function = armnn::ActivationFunction::BoundedReLu;
71 descriptor.m_Parameters.m_A = upperBound;
72 descriptor.m_Parameters.m_B = lowerBound;
73
74 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(descriptor, workloadInfo);
75
76 inputHandle->Allocate();
77 outputHandle->Allocate();
78
79 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
80
81 workload->Execute();
82
83 CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
84
85 result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, outputExpectedData);
86
87 return result;
88}
89
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +000090LayerTestResult<float, 4> BoundedReLuUpperAndLowerBoundTest(
91 armnn::IWorkloadFactory& workloadFactory,
92 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +000093{
94 unsigned int inputWidth = 4u;
95 unsigned int inputHeight = 5u;
96 unsigned int inputChannels = 1u;
97 unsigned int inputBatchSize = 1;
98
99 std::vector<float> input = std::vector<float>{
100 -2.0f, 0.1f, 0.5f, 1.25f,
101 0.786f, 0.9875f, -1.5f, 0.384f,
102 1.0001f, 3.5f, 7.5f, 0.896f,
103 2.126f, 2.0f, 0.3f, 0.15f,
104 0.999f, 1.2f, 0.89f, 6.1f,
105 };
106
telsoa01c577f2c2018-08-31 09:22:23 +0100107 // Calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000108 std::vector<float> output = std::vector<float>{
109 -1.0f, 0.1f, 0.5f, 1.0f,
110 0.786f, 0.9875f, -1.0f, 0.384f,
111 1.0f, 1.0f, 1.0f, 0.896f,
112 1.0f, 1.0f, 0.3f, 0.15f,
113 0.999f, 1.0f, 0.89f, 1.0f,
114 };
115
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000116 return BoundedReLuTestCommon<armnn::DataType::Float32>(
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000117 workloadFactory, memoryManager, 1.0f, -1.0f, 1.0f, 0, 1.0f, 0, input, output,
118 inputWidth, inputHeight, inputChannels, inputBatchSize);
telsoa014fcda012018-03-09 14:13:49 +0000119}
120
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000121LayerTestResult<float, 4> BoundedReLuUpperBoundOnlyTest(
122 armnn::IWorkloadFactory& workloadFactory,
123 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000124{
125 unsigned int inputWidth = 4u;
126 unsigned int inputHeight = 5u;
127 unsigned int inputChannels = 1u;
128 unsigned int inputBatchSize = 1;
129
130 std::vector<float> input = std::vector<float>{
131 -1.0f, 0.1f, 0.5f, 6.25f,
132 0.786f, 5.9875f, -0.5f, 0.384f,
133 6.0001f, 3.5f, 7.5f, 0.896f,
134 2.126f, 12.0f, 0.3f, 0.15f,
135 0.999f, 1.2f, 0.89f, 6.1f,
136 };
137
David Beckac42efd2018-09-26 17:41:13 +0100138 // Calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000139 std::vector<float> output = std::vector<float>{
140 0.0f, 0.1f, 0.5f, 6.0f,
141 0.786f, 5.9875f, 0.0f, 0.384f,
142 6.0f, 3.5f, 6.0f, 0.896f,
143 2.126f, 6.0f, 0.3f, 0.15f,
144 0.999f, 1.2f, 0.89f, 6.0f,
145 };
146
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000147 return BoundedReLuTestCommon<armnn::DataType::Float32>(
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000148 workloadFactory, memoryManager, 6.0f, 0.0f, 1.0f, 0, 1.0f, 0, input, output,
149 inputWidth, inputHeight, inputChannels, inputBatchSize);
telsoa014fcda012018-03-09 14:13:49 +0000150}
151
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000152LayerTestResult<uint8_t, 4> BoundedReLuUint8UpperBoundOnlyTest(
153 armnn::IWorkloadFactory& workloadFactory,
154 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000155{
156 unsigned int inputWidth = 3u;
157 unsigned int inputHeight = 2u;
158 unsigned int inputChannels = 1u;
159 unsigned int inputBatchSize = 1;
160
161 std::vector<uint8_t> input = std::vector<uint8_t>{
162 51, 124, 28,
163 251, 8, 92
164 };
165
David Beckac42efd2018-09-26 17:41:13 +0100166 // Calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000167 std::vector<uint8_t> output = std::vector<uint8_t>{
168 0, 122, 0,
169 255, 0, 58
170 };
171
172 float inputScale = 12.0f / 255.0f;
173 int32_t inputOffset = 63;
174 float outputScale = 6.0f / 255.0f;
175 int32_t outputOffset = 0;
176
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000177 return BoundedReLuTestCommon<armnn::DataType::QuantisedAsymm8>(
178 workloadFactory, memoryManager, 6.0f, 0.0f,
179 inputScale, inputOffset, outputScale, outputOffset,
180 input, output, inputWidth, inputHeight, inputChannels, inputBatchSize);
telsoa014fcda012018-03-09 14:13:49 +0000181}
182
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000183LayerTestResult<uint8_t, 4> BoundedReLuUint8UpperAndLowerBoundTest(
184 armnn::IWorkloadFactory& workloadFactory,
185 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000186{
187 unsigned int inputWidth = 3u;
188 unsigned int inputHeight = 2u;
189 unsigned int inputChannels = 1u;
190 unsigned int inputBatchSize = 1;
191
192 std::vector<uint8_t> input = std::vector<uint8_t>{
193 51, 230, 28,
194 251, 8, 92
195 };
196
telsoa01c577f2c2018-08-31 09:22:23 +0100197 // Calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000198 std::vector<uint8_t> output = std::vector<uint8_t>{
199 51, 192, 32,
200 192, 32, 92
201 };
202
203 int32_t inputOffset = 112;
204 float inputScale = 0.0125f;
205
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000206 return BoundedReLuTestCommon<armnn::DataType::QuantisedAsymm8>(
207 workloadFactory, memoryManager, 1.0f, -1.0f,
208 inputScale, inputOffset, inputScale, inputOffset, // Input/output scale & offset same.
209 input, output, inputWidth, inputHeight, inputChannels, inputBatchSize);
telsoa014fcda012018-03-09 14:13:49 +0000210}
211
212namespace
213{
214
215struct BoundedReLuRandomInputTestTraits
216{
217 constexpr static unsigned int inputHeight = 31u;
218 constexpr static unsigned int inputWidth = 19u;
219 constexpr static unsigned int inputChannels = 4u;
220 constexpr static unsigned int inputBatchSize = 2;
221
222 constexpr static unsigned int outputHeight = inputHeight;
223 constexpr static unsigned int outputWidth = inputWidth;
224 constexpr static unsigned int outputChannels = inputChannels;
225 constexpr static unsigned int outputBatchSize = inputBatchSize;
226
227 static armnn::TensorInfo GetInputTensorInfo()
228 {
229 return armnn::TensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth },
230 armnn::DataType::Float32);
231 }
232
233 static armnn::TensorInfo GetOutputTensorInfo()
234 {
235 return armnn::TensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth },
236 armnn::DataType::Float32);
237 }
238};
239
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000240boost::multi_array<float, 4> BoundedReLuRandomInputTest(
241 armnn::IWorkloadFactory& workloadFactory,
242 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
243 float lowerBound,
244 float upperBound,
245 const armnn::ActivationDescriptor& activationDescriptor)
telsoa014fcda012018-03-09 14:13:49 +0000246{
247 const armnn::TensorInfo inputTensorInfo = BoundedReLuRandomInputTestTraits::GetInputTensorInfo();
248 const armnn::TensorInfo outputTensorInfo = BoundedReLuRandomInputTestTraits::GetOutputTensorInfo();
249
250 boost::multi_array<float, 4> output(GetTensorShapeAsArray<4>(outputTensorInfo));
251
telsoa01c577f2c2018-08-31 09:22:23 +0100252 // Min/max random values passed to MakeRandomTensor are purposely outside of the ReLu
253 // range [lowerBound, upperBound].
telsoa014fcda012018-03-09 14:13:49 +0000254 auto input = MakeRandomTensor<float, 4>(inputTensorInfo, 4605828, lowerBound - 5.0f, upperBound * 2.0f);
255
256 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
257 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
258
telsoa01c577f2c2018-08-31 09:22:23 +0100259 // Set up bounded ReLu.
telsoa014fcda012018-03-09 14:13:49 +0000260 armnn::ActivationQueueDescriptor descriptor;
261 armnn::WorkloadInfo workloadInfo;
262 AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
263 AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
264 descriptor.m_Parameters = activationDescriptor;
265
266 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(descriptor, workloadInfo);
267
268 inputHandle->Allocate();
269 outputHandle->Allocate();
270
271 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
272
273 workload->Execute();
274
275 CopyDataFromITensorHandle(&output[0][0][0][0], outputHandle.get());
276
277 return output;
278}
279
280} // namespace
281
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000282LayerTestResult<float, 4> CompareBoundedReLuTest(
283 armnn::IWorkloadFactory& workloadFactory,
284 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
285 armnn::IWorkloadFactory& refWorkloadFactory,
286 float upperBound,
287 float lowerBound)
telsoa014fcda012018-03-09 14:13:49 +0000288{
289 LayerTestResult<float, 4> result(BoundedReLuRandomInputTestTraits::GetOutputTensorInfo());
290
291 armnn::ActivationDescriptor activationDescriptor;
292 activationDescriptor.m_Function = armnn::ActivationFunction::BoundedReLu;
293 activationDescriptor.m_A = upperBound;
294 activationDescriptor.m_B = lowerBound;
295
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000296 result.output = BoundedReLuRandomInputTest(
297 workloadFactory, memoryManager, 0.0f, upperBound, activationDescriptor);
298 result.outputExpected = BoundedReLuRandomInputTest(
299 refWorkloadFactory, nullptr, 0.0f, upperBound, activationDescriptor);
telsoa014fcda012018-03-09 14:13:49 +0000300
301 return result;
302}
303
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000304template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000305LayerTestResult<T,4> ConstantLinearActivationTestCommon(
306 armnn::IWorkloadFactory& workloadFactory,
307 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
308 float qScale = 0.0f,
309 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000310{
311 unsigned int inputHeight = 20;
312 unsigned int inputWidth = 17;
313 unsigned int inputChannels = 3;
314 unsigned int batchSize = 5;
315
316 armnn::TensorInfo inputTensorInfo;
317 armnn::TensorInfo outputTensorInfo;
318
319 unsigned int shape[] = {batchSize, inputChannels, inputHeight, inputWidth};
320
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000321 inputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
322 outputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +0000323
324 // Set quantization parameters if the requested type is a quantized type.
325 if(armnn::IsQuantizedType<T>())
326 {
327 inputTensorInfo.SetQuantizationScale(qScale);
328 inputTensorInfo.SetQuantizationOffset(qOffset);
329 outputTensorInfo.SetQuantizationScale(qScale);
330 outputTensorInfo.SetQuantizationOffset(qOffset);
331 }
332
333 LayerTestResult<T, 4> ret(outputTensorInfo);
334
335 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
336 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
337
telsoa01c577f2c2018-08-31 09:22:23 +0100338 // Do linear activation that should leave the tensor unchanged.
telsoa014fcda012018-03-09 14:13:49 +0000339 armnn::ActivationQueueDescriptor data;
340 armnn::WorkloadInfo info;
341 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
342 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
343 data.m_Parameters.m_A = 1.0f;
344 data.m_Parameters.m_B = 0.0f;
345 data.m_Parameters.m_Function = armnn::ActivationFunction::Linear;
346
347 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(data, info);
348
349 inputHandle->Allocate();
350 outputHandle->Allocate();
351
352 boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 7123561);
353 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
354
355 workload->Execute();
356
357 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
358
telsoa01c577f2c2018-08-31 09:22:23 +0100359 // Ensure output equals input.
telsoa014fcda012018-03-09 14:13:49 +0000360 ret.outputExpected = input;
361
362 return ret;
363}
364
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000365LayerTestResult<float, 4> ConstantLinearActivationTest(
366 armnn::IWorkloadFactory& workloadFactory,
367 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000368{
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000369 return ConstantLinearActivationTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager);
telsoa014fcda012018-03-09 14:13:49 +0000370}
371
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000372LayerTestResult<uint8_t, 4> ConstantLinearActivationUint8Test(
373 armnn::IWorkloadFactory& workloadFactory,
374 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000375{
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000376 return ConstantLinearActivationTestCommon<armnn::DataType::QuantisedAsymm8>(
377 workloadFactory, memoryManager, 4.0f, 3);
telsoa014fcda012018-03-09 14:13:49 +0000378}
379
Teresa Charlin18515e22019-04-24 10:17:46 +0100380LayerTestResult<int16_t, 4> ConstantLinearActivationInt16Test(
381 armnn::IWorkloadFactory& workloadFactory,
382 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
383{
384 return ConstantLinearActivationTestCommon<armnn::DataType::QuantisedSymm16>(
385 workloadFactory, memoryManager, 0.1f, 0);
386}
387
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000388template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000389LayerTestResult<T, 4> SimpleActivationTest(
390 armnn::IWorkloadFactory& workloadFactory,
391 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
392 armnn::ActivationFunction activationFunction,
393 float activationParameterA,
394 float activationParameterB,
395 float qScale,
396 int32_t qOffset,
397 const std::vector<float>& inputData,
398 const std::vector<float>& outputExpectedData)
telsoa014fcda012018-03-09 14:13:49 +0000399{
400 constexpr static unsigned int inputWidth = 16u;
401 constexpr static unsigned int inputHeight = 1u;
402 constexpr static unsigned int inputChannels = 1u;
403 constexpr static unsigned int inputBatchSize = 1u;
404
405 constexpr static unsigned int outputWidth = inputWidth;
406 constexpr static unsigned int outputHeight = inputHeight;
407 constexpr static unsigned int outputChannels = inputChannels;
408 constexpr static unsigned int outputBatchSize = inputBatchSize;
409
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000410 armnn::TensorInfo inputTensorInfo({ inputBatchSize, inputChannels, inputHeight, inputWidth }, ArmnnType);
411 armnn::TensorInfo outputTensorInfo({ outputBatchSize, outputChannels, outputHeight, outputWidth }, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +0000412
413 // Set quantization parameters if the requested type is a quantized type.
414 if(armnn::IsQuantizedType<T>())
415 {
416 inputTensorInfo.SetQuantizationScale(qScale);
417 inputTensorInfo.SetQuantizationOffset(qOffset);
418 outputTensorInfo.SetQuantizationScale(qScale);
419 outputTensorInfo.SetQuantizationOffset(qOffset);
420 }
421
422 LayerTestResult<T, 4> result(inputTensorInfo);
423
424 auto input = MakeTensor<T, 4>(inputTensorInfo, QuantizedVector<T>(qScale, qOffset, inputData));
425
426 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
427 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
428
telsoa01c577f2c2018-08-31 09:22:23 +0100429 // Setup bounded ReLu.
telsoa014fcda012018-03-09 14:13:49 +0000430 armnn::ActivationQueueDescriptor descriptor;
431 armnn::WorkloadInfo workloadInfo;
432 AddInputToWorkload(descriptor, workloadInfo, inputTensorInfo, inputHandle.get());
433 AddOutputToWorkload(descriptor, workloadInfo, outputTensorInfo, outputHandle.get());
434
435 descriptor.m_Parameters.m_Function = activationFunction;
436 descriptor.m_Parameters.m_A = activationParameterA;
437 descriptor.m_Parameters.m_B = activationParameterB;
438
439 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(descriptor, workloadInfo);
440
441 inputHandle->Allocate();
442 outputHandle->Allocate();
443
444 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
445
446 workload->Execute();
447
448 CopyDataFromITensorHandle(&result.output[0][0][0][0], outputHandle.get());
449
telsoa01c577f2c2018-08-31 09:22:23 +0100450 // Calculated manually.
telsoa014fcda012018-03-09 14:13:49 +0000451 result.outputExpected = MakeTensor<T, 4>(outputTensorInfo, QuantizedVector<T>(qScale, qOffset, outputExpectedData));
452
453 return result;
454}
455
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000456template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000457LayerTestResult<T, 4> SimpleSigmoidTestCommon(
458 armnn::IWorkloadFactory& workloadFactory,
459 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
460 float qScale,
461 int32_t qOffset)
telsoa014fcda012018-03-09 14:13:49 +0000462{
463 std::vector<float> inputData = {
464 -0.1f, -0.2f, -0.3f, -0.4f,
465 0.1f, 0.2f, 0.3f, 0.4f,
466 -1.0f, -2.0f, -3.0f, -4.0f,
467 1.0f, 2.0f, 3.0f, 4.0f
468 };
469
telsoa01c577f2c2018-08-31 09:22:23 +0100470 // Calculate output values for input.
telsoa014fcda012018-03-09 14:13:49 +0000471 auto f = [](float value)
472 {
473 return 1.0f / (1.0f + std::exp(-value));
474 };
475 std::vector<float> outputExpectedData(inputData.size());
476 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
477
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000478 return SimpleActivationTest<ArmnnType>(workloadFactory,
479 memoryManager,
480 armnn::ActivationFunction::Sigmoid,
481 0.f,
482 0.f,
483 qScale,
484 qOffset,
485 inputData,
486 outputExpectedData);
telsoa014fcda012018-03-09 14:13:49 +0000487}
488
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000489LayerTestResult<float, 4> SimpleSigmoidTest(
490 armnn::IWorkloadFactory& workloadFactory,
491 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000492{
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000493 return SimpleSigmoidTestCommon<armnn::DataType::Float32>(workloadFactory, memoryManager, 0.0f, 0);
telsoa014fcda012018-03-09 14:13:49 +0000494}
495
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000496LayerTestResult<uint8_t, 4> SimpleSigmoidUint8Test(
497 armnn::IWorkloadFactory& workloadFactory,
498 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
telsoa014fcda012018-03-09 14:13:49 +0000499{
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000500 return SimpleSigmoidTestCommon<armnn::DataType::QuantisedAsymm8>(workloadFactory, memoryManager, 0.1f, 50);
telsoa014fcda012018-03-09 14:13:49 +0000501}
502
Teresa Charlin18515e22019-04-24 10:17:46 +0100503LayerTestResult<int16_t, 4> SimpleSigmoidInt16Test(
504 armnn::IWorkloadFactory& workloadFactory,
505 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
506{
507 return SimpleSigmoidTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
508}
509
510template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
511LayerTestResult<T, 4> ReLuTestCommon(
512 armnn::IWorkloadFactory& workloadFactory,
513 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
514 float qScale,
515 int32_t qOffset)
516{
517 std::vector<float> inputData = {
518 -0.1f, -0.2f, -0.3f, -0.4f,
519 0.1f, 0.2f, 0.3f, 0.4f,
520 -1.0f, -2.0f, -3.0f, -4.0f,
521 1.0f, 2.0f, 3.0f, 4.0f
522 };
523
524 // Calculate output values for input.
525 auto f = [](float value)
526 {
527 return std::fmax(0.0f, value);
528 };
529 std::vector<float> outputExpectedData(inputData.size());
530 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
531
532 return SimpleActivationTest<ArmnnType>(workloadFactory,
533 memoryManager,
534 armnn::ActivationFunction::ReLu,
535 0.f,
536 0.f,
537 qScale,
538 qOffset,
539 inputData,
540 outputExpectedData);
541}
542
543LayerTestResult<int16_t, 4> ReLuInt16Test(
544 armnn::IWorkloadFactory& workloadFactory,
545 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
546{
547 return ReLuTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
548}
549
550
551template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
552LayerTestResult<T, 4> BoundedReLuTestCommon(
553 armnn::IWorkloadFactory& workloadFactory,
554 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
555 float qScale,
556 int32_t qOffset)
557{
558 std::vector<float> inputData = {
559 -0.1f, -0.2f, -0.3f, -0.4f,
560 0.1f, 0.2f, 0.3f, 0.4f,
561 -1.0f, -2.0f, -3.0f, -4.0f,
562 1.0f, 2.0f, 3.0f, 4.0f
563 };
564 const float a = 1.0f;
565 const float b = -1.0f;
566 // Calculate output values for input.
567 auto f = [a, b](float value)
568 {
569 return std::min(a, std::max(b, value));
570 };
571 std::vector<float> outputExpectedData(inputData.size());
572 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
573
574 return SimpleActivationTest<ArmnnType>(workloadFactory,
575 memoryManager,
576 armnn::ActivationFunction::BoundedReLu,
577 a,
578 b,
579 qScale,
580 qOffset,
581 inputData,
582 outputExpectedData);
583}
584
585LayerTestResult<int16_t, 4> BoundedReLuInt16Test(
586 armnn::IWorkloadFactory& workloadFactory,
587 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
588{
589 return ReLuTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
590}
591
592
593
594template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
595LayerTestResult<T, 4> SoftReLuTestCommon(
596 armnn::IWorkloadFactory& workloadFactory,
597 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
598 float qScale,
599 int32_t qOffset)
600{
601 std::vector<float> inputData = {
602 -0.1f, -0.2f, -0.3f, -0.4f,
603 0.1f, 0.2f, 0.3f, 0.4f,
604 -1.0f, -2.0f, -3.0f, -4.0f,
605 1.0f, 2.0f, 3.0f, 4.0f
606 };
607
608 // Calculate output values for input.
609 auto f = [](float value)
610 {
611 return std::log(1.0f + std::exp(value));
612 };
613 std::vector<float> outputExpectedData(inputData.size());
614 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
615
616 return SimpleActivationTest<ArmnnType>(workloadFactory,
617 memoryManager,
618 armnn::ActivationFunction::SoftReLu,
619 0.f,
620 0.f,
621 qScale,
622 qOffset,
623 inputData,
624 outputExpectedData);
625}
626
627LayerTestResult<int16_t, 4> SoftReLuInt16Test(
628 armnn::IWorkloadFactory& workloadFactory,
629 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
630{
631 return SoftReLuTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
632}
633
634template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
635LayerTestResult<T, 4> LeakyReLuTestCommon(
636 armnn::IWorkloadFactory& workloadFactory,
637 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
638 float qScale,
639 int32_t qOffset)
640{
641 std::vector<float> inputData = {
642 -0.1f, -0.2f, -0.3f, -0.4f,
643 0.1f, 0.2f, 0.3f, 0.4f,
644 -1.0f, -2.0f, -3.0f, -4.0f,
645 1.0f, 2.0f, 3.0f, 4.0f
646 };
647
648 const float a = 0.01f;
649 // Calculate output values for input.
650 auto f = [a](float value)
651 {
652 return value > 0.0f ? value : (value * a);
653 };
654 std::vector<float> outputExpectedData(inputData.size());
655 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
656
657 return SimpleActivationTest<ArmnnType>(workloadFactory,
658 memoryManager,
659 armnn::ActivationFunction::LeakyReLu,
660 a,
661 0.f,
662 qScale,
663 qOffset,
664 inputData,
665 outputExpectedData);
666}
667
668LayerTestResult<int16_t, 4> LeakyReLuInt16Test(
669 armnn::IWorkloadFactory& workloadFactory,
670 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
671{
672 return LeakyReLuTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
673}
674
675template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
676LayerTestResult<T, 4> AbsTestCommon(
677 armnn::IWorkloadFactory& workloadFactory,
678 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
679 float qScale,
680 int32_t qOffset)
681{
682 std::vector<float> inputData = {
683 -0.1f, -0.2f, -0.3f, -0.4f,
684 0.1f, 0.2f, 0.3f, 0.4f,
685 -1.0f, -2.0f, -3.0f, -4.0f,
686 1.0f, 2.0f, 3.0f, 4.0f
687 };
688
689 // Calculate output values for input.
690 auto f = [](float value)
691 {
692 return std::abs(value);
693 };
694 std::vector<float> outputExpectedData(inputData.size());
695 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
696
697 return SimpleActivationTest<ArmnnType>(workloadFactory,
698 memoryManager,
699 armnn::ActivationFunction::Abs,
700 0.f,
701 0.f,
702 qScale,
703 qOffset,
704 inputData,
705 outputExpectedData);
706}
707
708LayerTestResult<int16_t, 4> AbsInt16Test(
709 armnn::IWorkloadFactory& workloadFactory,
710 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
711{
712 return AbsTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
713}
714
715template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
716LayerTestResult<T, 4> SqrtTestCommon(
717 armnn::IWorkloadFactory& workloadFactory,
718 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
719 float qScale,
720 int32_t qOffset)
721{
722 std::vector<float> inputData = {
723 0.1f, 0.2f, 0.3f, 0.4f,
724 0.1f, 0.2f, 0.3f, 0.4f,
725 1.0f, 2.0f, 3.0f, 4.0f,
726 1.0f, 2.0f, 3.0f, 4.0f
727 };
728
729 // Calculate output values for input.
730 auto f = [](float value)
731 {
732 return std::sqrt(value);
733 };
734 std::vector<float> outputExpectedData(inputData.size());
735 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
736
737 return SimpleActivationTest<ArmnnType>(workloadFactory,
738 memoryManager,
739 armnn::ActivationFunction::Sqrt,
740 0.f,
741 0.f,
742 qScale,
743 qOffset,
744 inputData,
745 outputExpectedData);
746}
747
748LayerTestResult<int16_t, 4> SqrtInt16Test(
749 armnn::IWorkloadFactory& workloadFactory,
750 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
751{
752 return SqrtTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
753}
754
755template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
756LayerTestResult<T, 4> SquareTestCommon(
757 armnn::IWorkloadFactory& workloadFactory,
758 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
759 float qScale,
760 int32_t qOffset)
761{
762 std::vector<float> inputData = {
763 -0.1f, -0.2f, -0.3f, -0.4f,
764 0.1f, 0.2f, 0.3f, 0.4f,
765 -1.0f, -2.0f, -3.0f, -4.0f,
766 1.0f, 2.0f, 3.0f, 4.0f
767 };
768
769 // Calculate output values for input.
770 auto f = [](float value)
771 {
772 return std::pow(value,2);
773 };
774 std::vector<float> outputExpectedData(inputData.size());
775 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
776
777 return SimpleActivationTest<ArmnnType>(workloadFactory,
778 memoryManager,
779 armnn::ActivationFunction::Square,
780 0.f,
781 0.f,
782 qScale,
783 qOffset,
784 inputData,
785 outputExpectedData);
786}
787
788LayerTestResult<int16_t, 4> SquareInt16Test(
789 armnn::IWorkloadFactory& workloadFactory,
790 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
791{
792 return SquareTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
793}
794
795template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
796LayerTestResult<T, 4> TanhTestCommon(
797 armnn::IWorkloadFactory& workloadFactory,
798 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
799 float qScale,
800 int32_t qOffset)
801{
802 std::vector<float> inputData = {
803 -0.1f, -0.2f, -0.3f, -0.4f,
804 0.1f, 0.2f, 0.3f, 0.4f,
805 -1.0f, -2.0f, -3.0f, -4.0f,
806 1.0f, 2.0f, 3.0f, 4.0f
807 };
808
809 const float a = 2.0f;
810 const float b = 3.0f;
811 // Calculate output values for input.
812 auto f = [a, b](float value)
813 {
814 return a * tanhf(b * value);
815 };
816 std::vector<float> outputExpectedData(inputData.size());
817 std::transform(inputData.begin(), inputData.end(), outputExpectedData.begin(), f);
818
819 return SimpleActivationTest<ArmnnType>(workloadFactory,
820 memoryManager,
821 armnn::ActivationFunction::TanH,
822 a,
823 b,
824 qScale,
825 qOffset,
826 inputData,
827 outputExpectedData);
828}
829
830LayerTestResult<int16_t, 4> TanhInt16Test(
831 armnn::IWorkloadFactory& workloadFactory,
832 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager)
833{
834 return TanhTestCommon<armnn::DataType::QuantisedSymm16>(workloadFactory, memoryManager, 0.1f, 0);
835}
836
837
838
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000839template<armnn::DataType ArmnnType, typename T = armnn::ResolveType<ArmnnType>>
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000840LayerTestResult<T,4> CompareActivationTestImpl(
841 armnn::IWorkloadFactory& workloadFactory,
842 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
843 armnn::IWorkloadFactory& refWorkloadFactory,
844 armnn::ActivationFunction f,
845 unsigned int batchSize = 5,
846 float qScale = 0.0f,
847 int32_t qOffset = 0)
telsoa014fcda012018-03-09 14:13:49 +0000848{
849 unsigned int width = 17;
850 unsigned int height = 29;
851 unsigned int channels = 2;
852
853 float a = 0.234f;
854 float b = -12.345f;
855
856 armnn::TensorInfo inputTensorInfo;
857 armnn::TensorInfo outputTensorInfo;
858
859 unsigned int shape[] = {batchSize, channels, height, width};
860
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000861 inputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
862 outputTensorInfo = armnn::TensorInfo(4, shape, ArmnnType);
telsoa014fcda012018-03-09 14:13:49 +0000863
864 // Set quantization parameters if the requested type is a quantized type.
865 if(armnn::IsQuantizedType<T>())
866 {
867 inputTensorInfo.SetQuantizationScale(qScale);
868 inputTensorInfo.SetQuantizationOffset(qOffset);
869 outputTensorInfo.SetQuantizationScale(qScale);
870 outputTensorInfo.SetQuantizationOffset(qOffset);
871 }
872
873 float minVal = -10.f;
874 if (f == armnn::ActivationFunction::Sqrt)
875 {
876 minVal = 0.f;
877 }
878
879 boost::multi_array<T, 4> input = MakeRandomTensor<T, 4>(inputTensorInfo, 21453, minVal, 10.f);
880
881
882 LayerTestResult<T,4> ret(outputTensorInfo);
883 auto boostArrayExtents = boost::extents
884 [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(batchSize)]
885 [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(channels)]
886 [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(height)]
887 [boost::numeric_cast<boost::multi_array_types::extent_gen::index>(width)];
888 ret.output.resize(boostArrayExtents);
889 ret.outputExpected.resize(boostArrayExtents);
890
891
892 std::unique_ptr<armnn::ITensorHandle> inputHandle = workloadFactory.CreateTensorHandle(inputTensorInfo);
893 std::unique_ptr<armnn::ITensorHandle> outputHandle = workloadFactory.CreateTensorHandle(outputTensorInfo);
894
895 std::unique_ptr<armnn::ITensorHandle> inputHandleRef = refWorkloadFactory.CreateTensorHandle(inputTensorInfo);
896 std::unique_ptr<armnn::ITensorHandle> outputHandleRef = refWorkloadFactory.CreateTensorHandle(outputTensorInfo);
897
898 armnn::ActivationQueueDescriptor data;
899 armnn::WorkloadInfo info;
900 AddInputToWorkload(data, info, inputTensorInfo, inputHandle.get());
901 AddOutputToWorkload(data, info, outputTensorInfo, outputHandle.get());
902 data.m_Parameters.m_A = a;
903 data.m_Parameters.m_B = b;
904 data.m_Parameters.m_Function = f;
905
906 armnn::ActivationQueueDescriptor refData = data;
907 armnn::WorkloadInfo refInfo = info;
908 SetWorkloadInput(refData, refInfo, 0, inputTensorInfo, inputHandleRef.get());
909 SetWorkloadOutput(refData, refInfo, 0, outputTensorInfo, outputHandleRef.get());
910
911 std::unique_ptr<armnn::IWorkload> workload = workloadFactory.CreateActivation(data, info);
912 BOOST_ASSERT(workload != nullptr);
913 std::unique_ptr<armnn::IWorkload> workloadRef = refWorkloadFactory.CreateActivation(refData, refInfo);
914 BOOST_ASSERT(workloadRef != nullptr);
915
916 inputHandle->Allocate();
917 outputHandle->Allocate();
918 inputHandleRef->Allocate();
919 outputHandleRef->Allocate();
920
921 CopyDataToITensorHandle(inputHandle.get(), &input[0][0][0][0]);
922 CopyDataToITensorHandle(inputHandleRef.get(), &input[0][0][0][0]);
923
924 workload->Execute();
925 workloadRef->Execute();
926
927 CopyDataFromITensorHandle(&ret.output[0][0][0][0], outputHandle.get());
928 CopyDataFromITensorHandle(&ret.outputExpected[0][0][0][0], outputHandleRef.get());
929
930 return ret;
931}
932
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000933LayerTestResult<float,4> CompareActivationTest(
934 armnn::IWorkloadFactory& workloadFactory,
935 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
936 armnn::IWorkloadFactory& refWorkloadFactory,
937 armnn::ActivationFunction f,
938 unsigned int batchSize)
telsoa014fcda012018-03-09 14:13:49 +0000939{
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000940 return CompareActivationTestImpl<armnn::DataType::Float32>(
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000941 workloadFactory, memoryManager, refWorkloadFactory, f, batchSize);
telsoa014fcda012018-03-09 14:13:49 +0000942}
943
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000944LayerTestResult<uint8_t,4> CompareActivationUint8Test(
945 armnn::IWorkloadFactory& workloadFactory,
946 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
947 armnn::IWorkloadFactory& refWorkloadFactory,
948 armnn::ActivationFunction f)
telsoa014fcda012018-03-09 14:13:49 +0000949{
Nattapat Chaimanowong649dd952019-01-22 16:10:44 +0000950 return CompareActivationTestImpl<armnn::DataType::QuantisedAsymm8>(
Aron Virginas-Tar5caf9072018-11-14 18:35:18 +0000951 workloadFactory, memoryManager, refWorkloadFactory, f, 5, 0.1f, 50);
telsoa014fcda012018-03-09 14:13:49 +0000952}
Teresa Charlin18515e22019-04-24 10:17:46 +0100953
954LayerTestResult<int16_t,4> CompareActivationInt16Test(
955 armnn::IWorkloadFactory& workloadFactory,
956 const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager,
957 armnn::IWorkloadFactory& refWorkloadFactory,
958 armnn::ActivationFunction f)
959{
960 return CompareActivationTestImpl<armnn::DataType::QuantisedSymm16>(
961 workloadFactory, memoryManager, refWorkloadFactory, f, 5, 0.1f, 0);
962}