blob: f64d380423c23d38d942025696d30604777a014c [file] [log] [blame]
Georgios Pinitas12833d02019-07-25 13:31:10 +01001/*
Sheri Zhangcece42c2021-02-10 15:32:38 +00002 * Copyright (c) 2019-2021 Arm Limited.
Georgios Pinitas12833d02019-07-25 13:31:10 +01003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "arm_compute/runtime/RuntimeContext.h"
25
Georgios Pinitas12833d02019-07-25 13:31:10 +010026#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h"
Pablo Telloebaddb62019-10-17 14:21:16 +010027#include "arm_compute/runtime/SchedulerFactory.h"
Georgios Pinitas12833d02019-07-25 13:31:10 +010028#include "arm_compute/runtime/Tensor.h"
Georgios Pinitas12833d02019-07-25 13:31:10 +010029#include "tests/Globals.h"
30#include "tests/NEON/Accessor.h"
31#include "tests/Utils.h"
32#include "tests/framework/Asserts.h"
33#include "tests/framework/Macros.h"
34#include "tests/validation/Validation.h"
35#include "tests/validation/reference/ActivationLayer.h"
36
37#include <memory>
38#include <random>
39#if !defined(BARE_METAL)
40#include <thread>
41#endif // !defined(BARE_METAL)
42
43namespace arm_compute
44{
45namespace test
46{
47namespace validation
48{
49TEST_SUITE(NEON)
50TEST_SUITE(UNIT)
51TEST_SUITE(RuntimeContext)
52
53TEST_CASE(Scheduler, framework::DatasetMode::ALL)
54{
55 using namespace arm_compute;
56 // Create a runtime context object
57 RuntimeContext ctx;
58
59 // Check if it's been initialised properly
60 ARM_COMPUTE_EXPECT(ctx.scheduler() != nullptr, framework::LogLevel::ERRORS);
61 ARM_COMPUTE_EXPECT(ctx.asset_manager() == nullptr, framework::LogLevel::ERRORS);
62
Pablo Telloebaddb62019-10-17 14:21:16 +010063 // Create a Scheduler
64 auto scheduler = SchedulerFactory::create();
65 ctx.set_scheduler(scheduler.get());
Georgios Pinitas12833d02019-07-25 13:31:10 +010066 // Check if the scheduler has been properly setup
67 ARM_COMPUTE_EXPECT(ctx.scheduler() != nullptr, framework::LogLevel::ERRORS);
68
69 // Create a new activation function
70 NEActivationLayer act_layer(&ctx);
71
72 Tensor src = create_tensor<Tensor>(TensorShape(32, 32), DataType::F32, 1);
73 Tensor dst = create_tensor<Tensor>(TensorShape(32, 32), DataType::F32, 1);
74
75 act_layer.configure(&src, &dst, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LINEAR));
76
77 ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
78 ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
79
80 // Allocate tensors
81 src.allocator()->allocate();
82 dst.allocator()->allocate();
83
84 ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
85
86 float min_bound = 0;
87 float max_bound = 0;
88 std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<float>(ActivationLayerInfo::ActivationFunction::LINEAR, DataType::F32);
89 std::uniform_real_distribution<> distribution(min_bound, max_bound);
90 library->fill(Accessor(src), distribution, 0);
91
92 // Compute function
93 act_layer.run();
94}
95
96#if !defined(BARE_METAL)
97// This test tries scheduling work concurrently from two independent threads
98TEST_CASE(MultipleThreadedScheduller, framework::DatasetMode::ALL)
99{
100 // Create a runtime context object for thread 1
101 RuntimeContext ctx1;
102
103 // Create a runtime context object for thread 2
104 RuntimeContext ctx2;
105
106 // Create a new activation function
107 NEActivationLayer act_layer_thread0(&ctx1);
108 NEActivationLayer act_layer_thread1(&ctx2);
109
110 const TensorShape tensor_shape(128, 128);
111 Tensor src_t0 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
112 Tensor dst_t0 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
113 Tensor src_t1 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
114 Tensor dst_t1 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
115 ActivationLayerInfo activation_info(ActivationLayerInfo::ActivationFunction::LINEAR);
116
117 act_layer_thread0.configure(&src_t0, &dst_t0, activation_info);
118 act_layer_thread1.configure(&src_t1, &dst_t1, activation_info);
119
120 ARM_COMPUTE_EXPECT(src_t0.info()->is_resizable(), framework::LogLevel::ERRORS);
121 ARM_COMPUTE_EXPECT(dst_t0.info()->is_resizable(), framework::LogLevel::ERRORS);
122 ARM_COMPUTE_EXPECT(src_t1.info()->is_resizable(), framework::LogLevel::ERRORS);
123 ARM_COMPUTE_EXPECT(dst_t1.info()->is_resizable(), framework::LogLevel::ERRORS);
124
125 // Allocate tensors
126 src_t0.allocator()->allocate();
127 dst_t0.allocator()->allocate();
128 src_t1.allocator()->allocate();
129 dst_t1.allocator()->allocate();
130
131 ARM_COMPUTE_EXPECT(!src_t0.info()->is_resizable(), framework::LogLevel::ERRORS);
132 ARM_COMPUTE_EXPECT(!src_t1.info()->is_resizable(), framework::LogLevel::ERRORS);
133
134 float min_bound = 0;
135 float max_bound = 0;
136 std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<float>(ActivationLayerInfo::ActivationFunction::LINEAR, DataType::F32);
137 std::uniform_real_distribution<> distribution(min_bound, max_bound);
138 library->fill(Accessor(src_t0), distribution, 0);
139 library->fill(Accessor(src_t1), distribution, 0);
140
141 std::thread neon_thread1([&] { act_layer_thread0.run(); });
142 std::thread neon_thread2([&] { act_layer_thread1.run(); });
143
144 neon_thread1.join();
145 neon_thread2.join();
146
147 Window window;
148 window.use_tensor_dimensions(dst_t0.info()->tensor_shape());
149 Iterator t0_it(&dst_t0, window);
150 Iterator t1_it(&dst_t1, window);
151 execute_window_loop(window, [&](const Coordinates &)
152 {
153 const bool match = (*reinterpret_cast<float *>(t0_it.ptr()) == *reinterpret_cast<float *>(t1_it.ptr()));
154 ARM_COMPUTE_EXPECT(match, framework::LogLevel::ERRORS);
155 },
156 t0_it, t1_it);
157}
158#endif // !defined(BARE_METAL)
159
160TEST_SUITE_END() // RuntimeContext
161TEST_SUITE_END() // UNIT
Sheri Zhangcece42c2021-02-10 15:32:38 +0000162TEST_SUITE_END() // Neon
Georgios Pinitas12833d02019-07-25 13:31:10 +0100163} // namespace validation
164} // namespace test
165} // namespace arm_compute