aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arm_compute/runtime/CL/functions/CLActivationLayer.h15
-rw-r--r--arm_compute/runtime/CPP/CPPScheduler.h21
-rw-r--r--arm_compute/runtime/DeviceProperties.h41
-rw-r--r--arm_compute/runtime/GLES_COMPUTE/functions/GCActivationLayer.h17
-rw-r--r--arm_compute/runtime/IAssetManager.h40
-rw-r--r--arm_compute/runtime/IRuntimeContext.h61
-rw-r--r--arm_compute/runtime/NEON/INESimpleFunctionNoBorder.h19
-rw-r--r--arm_compute/runtime/NEON/functions/NEActivationLayer.h14
-rw-r--r--arm_compute/runtime/OMP/OMPScheduler.h16
-rw-r--r--arm_compute/runtime/RuntimeContext.h64
-rw-r--r--arm_compute/runtime/Scheduler.h8
-rw-r--r--arm_compute/runtime/SchedulerFactory.h58
-rw-r--r--arm_compute/runtime/SingleThreadScheduler.h17
-rw-r--r--arm_compute/runtime/Utils.h13
-rw-r--r--src/runtime/CL/functions/CLActivationLayer.cpp10
-rw-r--r--src/runtime/CPP/CPPScheduler.cpp62
-rw-r--r--src/runtime/CPP/SingleThreadScheduler.cpp8
-rw-r--r--src/runtime/DeviceProperties.cpp34
-rw-r--r--src/runtime/GLES_COMPUTE/functions/GCActivationLayer.cpp10
-rw-r--r--src/runtime/NEON/INESimpleFunctionNoBorder.cpp10
-rw-r--r--src/runtime/NEON/functions/NEActivationLayer.cpp12
-rw-r--r--src/runtime/OMP/OMPScheduler.cpp11
-rw-r--r--src/runtime/RuntimeContext.cpp56
-rw-r--r--src/runtime/Scheduler.cpp107
-rw-r--r--src/runtime/SchedulerFactory.cpp82
-rw-r--r--src/runtime/Utils.cpp26
-rw-r--r--tests/Globals.h6
-rw-r--r--tests/ParametersLibrary.cpp41
-rw-r--r--tests/ParametersLibrary.h76
-rw-r--r--tests/Utils.h3
-rw-r--r--tests/benchmark/fixtures/ActivationLayerFixture.h13
-rw-r--r--tests/framework/Framework.cpp12
-rw-r--r--tests/framework/Framework.h9
-rw-r--r--tests/framework/instruments/Instruments.h9
-rw-r--r--tests/framework/instruments/SchedulerTimer.cpp28
-rw-r--r--tests/framework/instruments/SchedulerTimer.h27
-rw-r--r--tests/instruments/Helpers.h86
-rw-r--r--tests/main.cpp32
-rw-r--r--tests/validation/CL/ActivationLayer.cpp1
-rw-r--r--tests/validation/NEON/ActivationLayer.cpp6
-rw-r--r--tests/validation/NEON/UNIT/RuntimeContext.cpp166
-rw-r--r--tests/validation/fixtures/ActivationLayerFixture.h3
42 files changed, 1179 insertions, 171 deletions
diff --git a/arm_compute/runtime/CL/functions/CLActivationLayer.h b/arm_compute/runtime/CL/functions/CLActivationLayer.h
index c10c5301c2..1201d7d355 100644
--- a/arm_compute/runtime/CL/functions/CLActivationLayer.h
+++ b/arm_compute/runtime/CL/functions/CLActivationLayer.h
@@ -39,6 +39,19 @@ class ICLTensor;
class CLActivationLayer : public ICLSimpleFunction
{
public:
+ /** Constructor
+ *
+ * @param[in] ctx Runtime context to be used by the function
+ */
+ CLActivationLayer(void *ctx = nullptr);
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ CLActivationLayer(const CLActivationLayer &) = delete;
+ /** Default move constructor */
+ CLActivationLayer(CLActivationLayer &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ CLActivationLayer &operator=(const CLActivationLayer &) = delete;
+ /** Default move assignment operator */
+ CLActivationLayer &operator=(CLActivationLayer &&) = default;
/** Set the input and output tensor.
*
* @note If the output tensor is a nullptr or is equal to the input, the activation function will be performed in-place
@@ -60,5 +73,5 @@ public:
*/
static Status validate(const ITensorInfo *input, const ITensorInfo *output, const ActivationLayerInfo &act_info);
};
-}
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_CLACTIVATIONLAYER_H__ */
diff --git a/arm_compute/runtime/CPP/CPPScheduler.h b/arm_compute/runtime/CPP/CPPScheduler.h
index 17ed8310a4..69cd25f994 100644
--- a/arm_compute/runtime/CPP/CPPScheduler.h
+++ b/arm_compute/runtime/CPP/CPPScheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018 ARM Limited.
+ * Copyright (c) 2016-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,14 +26,18 @@
#include "arm_compute/runtime/IScheduler.h"
-#include <list>
+#include <memory>
namespace arm_compute
{
/** C++11 implementation of a pool of threads to automatically split a kernel's execution among several threads. */
-class CPPScheduler : public IScheduler
+class CPPScheduler final : public IScheduler
{
public:
+ /** Constructor: create a pool of threads. */
+ CPPScheduler();
+ /** Default destructor */
+ ~CPPScheduler();
/** Sets the number of threads the scheduler will use to run the kernels.
*
* @param[in] num_threads If set to 0, then the maximum number of threads supported by C++11 will be used, otherwise the number of threads specified.
@@ -47,6 +51,7 @@ public:
/** Access the scheduler singleton
*
+ * @note this method has been deprecated and will be remover in the upcoming releases
* @return The scheduler
*/
static CPPScheduler &get();
@@ -69,12 +74,8 @@ protected:
void run_workloads(std::vector<Workload> &workloads) override;
private:
- class Thread;
- /** Constructor: create a pool of threads. */
- CPPScheduler();
-
- unsigned int _num_threads;
- std::list<Thread> _threads;
+ struct Impl;
+ std::unique_ptr<Impl> _impl;
};
-}
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_CPPSCHEDULER_H__ */
diff --git a/arm_compute/runtime/DeviceProperties.h b/arm_compute/runtime/DeviceProperties.h
new file mode 100644
index 0000000000..b411124a04
--- /dev/null
+++ b/arm_compute/runtime/DeviceProperties.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_DEVICE_PROPERTIES_H__
+#define __ARM_COMPUTE_DEVICE_PROPERTIES_H__
+
+#include "arm_compute/core/CPP/CPPTypes.h"
+
+namespace arm_compute
+{
+/** Device properties */
+struct DeviceProperties
+{
+ std::string name{ "unknown" };
+ CPUInfo cpu_info{}; // initialised upon creating in the constructor
+
+ DeviceProperties();
+};
+
+} // namespace arm_compute
+#endif /*__ARM_COMPUTE_DEVICE_PROPERTIES_H__ */
diff --git a/arm_compute/runtime/GLES_COMPUTE/functions/GCActivationLayer.h b/arm_compute/runtime/GLES_COMPUTE/functions/GCActivationLayer.h
index b43456b2cd..5e0effe902 100644
--- a/arm_compute/runtime/GLES_COMPUTE/functions/GCActivationLayer.h
+++ b/arm_compute/runtime/GLES_COMPUTE/functions/GCActivationLayer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -38,6 +38,19 @@ class IGCTensor;
class GCActivationLayer : public IGCSimpleFunction
{
public:
+ /** Constructor
+ *
+ * @param[in] ctx Runtime context to be used by the function
+ */
+ GCActivationLayer(void *ctx = nullptr);
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ GCActivationLayer(const GCActivationLayer &) = delete;
+ /** Default move constructor */
+ GCActivationLayer(GCActivationLayer &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ GCActivationLayer &operator=(const GCActivationLayer &) = delete;
+ /** Default move assignment operator */
+ GCActivationLayer &operator=(GCActivationLayer &&) = default;
/** Set the input and output tensor.
*
* @note If the output tensor is a nullptr, the activation function will be performed in-place
@@ -49,5 +62,5 @@ public:
*/
void configure(IGCTensor *input, IGCTensor *output, ActivationLayerInfo act_info);
};
-}
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_GCACTIVATIONLAYER_H__ */
diff --git a/arm_compute/runtime/IAssetManager.h b/arm_compute/runtime/IAssetManager.h
new file mode 100644
index 0000000000..d6f501a9e0
--- /dev/null
+++ b/arm_compute/runtime/IAssetManager.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_IASSET_MANAGER_H__
+#define __ARM_COMPUTE_IASSET_MANAGER_H__
+
+namespace arm_compute
+{
+/** Asset manager interface */
+class IAssetManager
+{
+public:
+ /** Memory manager accessor
+ *
+ * @return Memory manager
+ */
+ virtual IMemoryManager *memory_manager() = 0;
+};
+} // namespace arm_compute
+#endif /*__ARM_COMPUTE_IASSET_MANAGER_H__ */
diff --git a/arm_compute/runtime/IRuntimeContext.h b/arm_compute/runtime/IRuntimeContext.h
new file mode 100644
index 0000000000..f928085682
--- /dev/null
+++ b/arm_compute/runtime/IRuntimeContext.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_IRUNTIME_CONTEXT_H__
+#define __ARM_COMPUTE_IRUNTIME_CONTEXT_H__
+
+namespace arm_compute
+{
+// Forward declarations
+class IScheduler;
+class IAssetManager;
+class DeviceProperties;
+
+/** Context interface */
+class IRuntimeContext
+{
+public:
+ /** Destructor */
+ virtual ~IRuntimeContext() = default;
+ /** Scheduler accessor
+ *
+ * @note Scheduler is used to schedule workloads
+ *
+ * @return The scheduler registered to the context
+ */
+ virtual IScheduler *scheduler() = 0;
+ /** Asset manager accessor
+ *
+ * @note Asset manager is used to manage objects/tensors within functions
+ *
+ * @return The asset manager registered to the context
+ */
+ virtual IAssetManager *asset_manager() = 0;
+ /** Device propertied accessor
+ *
+ * @return Device properties
+ */
+ virtual const DeviceProperties &properties() = 0;
+};
+} // namespace arm_compute
+#endif /*__ARM_COMPUTE_IRUNTIME_CONTEXT_H__ */
diff --git a/arm_compute/runtime/NEON/INESimpleFunctionNoBorder.h b/arm_compute/runtime/NEON/INESimpleFunctionNoBorder.h
index 6765b5f937..d0c3a9beb5 100644
--- a/arm_compute/runtime/NEON/INESimpleFunctionNoBorder.h
+++ b/arm_compute/runtime/NEON/INESimpleFunctionNoBorder.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -26,6 +26,7 @@
#include "arm_compute/core/NEON/INEKernel.h"
#include "arm_compute/runtime/IFunction.h"
+#include "arm_compute/runtime/IRuntimeContext.h"
#include <memory>
@@ -35,14 +36,26 @@ namespace arm_compute
class INESimpleFunctionNoBorder : public IFunction
{
public:
- /** Constructor */
- INESimpleFunctionNoBorder();
+ /** Constructor
+ *
+ * @param[in] ctx Runtime context to be used by the function
+ */
+ INESimpleFunctionNoBorder(IRuntimeContext *ctx = nullptr);
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ INESimpleFunctionNoBorder(const INESimpleFunctionNoBorder &) = delete;
+ /** Default move constructor */
+ INESimpleFunctionNoBorder(INESimpleFunctionNoBorder &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ INESimpleFunctionNoBorder &operator=(const INESimpleFunctionNoBorder &) = delete;
+ /** Default move assignment operator */
+ INESimpleFunctionNoBorder &operator=(INESimpleFunctionNoBorder &&) = default;
// Inherited methods overridden:
void run() override final;
protected:
std::unique_ptr<INEKernel> _kernel; /**< Kernel to run */
+ IRuntimeContext *_ctx; /**< Context to use */
};
} // namespace arm_compute
#endif /*__ARM_COMPUTE_INESIMPLEFUNCTIONNOBORDER_H__ */
diff --git a/arm_compute/runtime/NEON/functions/NEActivationLayer.h b/arm_compute/runtime/NEON/functions/NEActivationLayer.h
index c0b5f7ab37..d383da4f32 100644
--- a/arm_compute/runtime/NEON/functions/NEActivationLayer.h
+++ b/arm_compute/runtime/NEON/functions/NEActivationLayer.h
@@ -30,6 +30,7 @@
namespace arm_compute
{
+// Forward declarations
class ITensor;
/** Basic function to run @ref NEActivationLayerKernel
@@ -39,6 +40,19 @@ class ITensor;
class NEActivationLayer : public INESimpleFunctionNoBorder
{
public:
+ /** Constructor
+ *
+ * @param[in] ctx Runtime context to be used by the function
+ */
+ NEActivationLayer(IRuntimeContext *ctx = nullptr);
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ NEActivationLayer(const NEActivationLayer &) = delete;
+ /** Default move constructor */
+ NEActivationLayer(NEActivationLayer &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ NEActivationLayer &operator=(const NEActivationLayer &) = delete;
+ /** Default move assignment operator */
+ NEActivationLayer &operator=(NEActivationLayer &&) = default;
/** Set the input and output tensor.
*
* @note If the output tensor is a nullptr or is equal to the input, the activation function will be performed in-place
diff --git a/arm_compute/runtime/OMP/OMPScheduler.h b/arm_compute/runtime/OMP/OMPScheduler.h
index ff9bf052fd..5934ee1c12 100644
--- a/arm_compute/runtime/OMP/OMPScheduler.h
+++ b/arm_compute/runtime/OMP/OMPScheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,9 +29,11 @@
namespace arm_compute
{
/** Pool of threads to automatically split a kernel's execution among several threads. */
-class OMPScheduler : public IScheduler
+class OMPScheduler final : public IScheduler
{
public:
+ /** Constructor. */
+ OMPScheduler();
/** Sets the number of threads the scheduler will use to run the kernels.
*
* @param[in] num_threads If set to 0, then the number returned by omp_get_max_threads() will be used, otherwise the number of threads specified.
@@ -42,11 +44,6 @@ public:
* @return Number of threads available in OMPScheduler.
*/
unsigned int num_threads() const override;
- /** Access the scheduler singleton
- *
- * @return The scheduler
- */
- static OMPScheduler &get();
/** Multithread the execution of the passed kernel if possible.
*
* The kernel will run on a single thread if any of these conditions is true:
@@ -68,10 +65,7 @@ protected:
void run_workloads(std::vector<Workload> &workloads) override;
private:
- /** Constructor. */
- OMPScheduler();
-
unsigned int _num_threads;
};
-}
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_OMPSCHEDULER_H__ */
diff --git a/arm_compute/runtime/RuntimeContext.h b/arm_compute/runtime/RuntimeContext.h
new file mode 100644
index 0000000000..564ba78e63
--- /dev/null
+++ b/arm_compute/runtime/RuntimeContext.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_RUNTIME_CONTEXT_H__
+#define __ARM_COMPUTE_RUNTIME_CONTEXT_H__
+
+#include "arm_compute/runtime/DeviceProperties.h"
+#include "arm_compute/runtime/IRuntimeContext.h"
+
+#include <memory>
+
+namespace arm_compute
+{
+/** Runtime context */
+class RuntimeContext : public IRuntimeContext
+{
+public:
+ /** Default Constructor */
+ RuntimeContext();
+ /** Destructor */
+ ~RuntimeContext() = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ RuntimeContext(const RuntimeContext &) = delete;
+ /** Default move constructor */
+ RuntimeContext(RuntimeContext &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ RuntimeContext &operator=(const RuntimeContext &) = delete;
+ /** Default move assignment operator */
+ RuntimeContext &operator=(RuntimeContext &&) = default;
+ /** CPU Scheduler setter */
+ void set_scheduler(IScheduler *scheduler);
+
+ // Inherited overridden methods
+ IScheduler *scheduler() override;
+ IAssetManager *asset_manager() override;
+ const DeviceProperties &properties() override;
+
+private:
+ std::unique_ptr<IScheduler> _owned_scheduler{ nullptr };
+ IScheduler *_scheduler{ nullptr };
+ DeviceProperties _device_props{};
+};
+} // namespace arm_compute
+#endif /*__ARM_COMPUTE_RUNTIME_CONTEXT_H__ */
diff --git a/arm_compute/runtime/Scheduler.h b/arm_compute/runtime/Scheduler.h
index 7e10461b5a..89263fd176 100644
--- a/arm_compute/runtime/Scheduler.h
+++ b/arm_compute/runtime/Scheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,6 +25,8 @@
#define __ARM_COMPUTE_SCHEDULER_H__
#include "arm_compute/runtime/IScheduler.h"
+
+#include <map>
#include <memory>
namespace arm_compute
@@ -74,7 +76,9 @@ public:
private:
static Type _scheduler_type;
static std::shared_ptr<IScheduler> _custom_scheduler;
+ static std::map<Type, std::unique_ptr<IScheduler>> _schedulers;
+
Scheduler();
};
-}
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_SCHEDULER_H__ */
diff --git a/arm_compute/runtime/SchedulerFactory.h b/arm_compute/runtime/SchedulerFactory.h
new file mode 100644
index 0000000000..3e35655a19
--- /dev/null
+++ b/arm_compute/runtime/SchedulerFactory.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_SCHEDULER_FACTORY_H__
+#define __ARM_COMPUTE_SCHEDULER_FACTORY_H__
+
+#include "arm_compute/runtime/IScheduler.h"
+
+#include <memory>
+
+namespace arm_compute
+{
+/** Scheduler Factory */
+class SchedulerFactory
+{
+public:
+ /** Scheduler type */
+ enum class Type
+ {
+ ST, /**< Single thread. */
+ CPP, /**< C++11 threads. */
+ OMP, /**< OpenMP. */
+ };
+
+public:
+ /** Create a scheduler depending on the scheduler type
+ *
+ * @param[in] type Type of scheduler to create
+ *
+ * @return Scheduler
+ */
+ static std::unique_ptr<IScheduler> create(Type type = _default_type);
+
+private:
+ static const Type _default_type;
+};
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_SCHEDULER_H__ */
diff --git a/arm_compute/runtime/SingleThreadScheduler.h b/arm_compute/runtime/SingleThreadScheduler.h
index 7c084efeaf..9ea0f0818e 100644
--- a/arm_compute/runtime/SingleThreadScheduler.h
+++ b/arm_compute/runtime/SingleThreadScheduler.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,9 +29,11 @@
namespace arm_compute
{
/** Pool of threads to automatically split a kernel's execution among several threads. */
-class SingleThreadScheduler : public IScheduler
+class SingleThreadScheduler final : public IScheduler
{
public:
+ /** Constructor. */
+ SingleThreadScheduler() = default;
/** Sets the number of threads the scheduler will use to run the kernels.
*
* @param[in] num_threads This is ignored for this scheduler as the number of threads is always one.
@@ -42,11 +44,6 @@ public:
* @return Number of threads available in SingleThreadScheduler.
*/
unsigned int num_threads() const override;
- /** Access the scheduler singleton
- *
- * @return The scheduler
- */
- static SingleThreadScheduler &get();
/** Runs the kernel in the same thread as the caller synchronously.
*
* @param[in] kernel Kernel to execute.
@@ -60,10 +57,6 @@ protected:
* @param[in] workloads Workloads to run
*/
void run_workloads(std::vector<Workload> &workloads) override;
-
-private:
- /** Constructor. */
- SingleThreadScheduler() = default;
};
-}
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_SINGLETHREADSCHEDULER_H__ */
diff --git a/arm_compute/runtime/Utils.h b/arm_compute/runtime/Utils.h
index 2f037a0621..15c0042a33 100644
--- a/arm_compute/runtime/Utils.h
+++ b/arm_compute/runtime/Utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,6 +24,7 @@
#ifndef __ARM_COMPUTE_RUNTIME_UTILS_H__
#define __ARM_COMPUTE_RUNTIME_UTILS_H__
+#include "arm_compute/runtime/IRuntimeContext.h"
#include "arm_compute/runtime/Scheduler.h"
#include <string>
@@ -37,5 +38,13 @@ namespace arm_compute
* @return The string describing the scheduler type.
*/
const std::string &string_from_scheduler_type(Scheduler::Type t);
-}
+
+/** Schedules a kernel using the context if not nullptr else uses the legacy scheduling flow.
+ *
+ * @param[in] ctx Context to use.
+ * @param[in] kernel Kernel to schedule.
+ * @param[in] hints Hints to use.
+ */
+void schedule_kernel_on_ctx(IRuntimeContext *ctx, ICPPKernel *kernel, const IScheduler::Hints &hints);
+} // namespace arm_compute
#endif /* __ARM_COMPUTE_RUNTIME_UTILS_H__ */
diff --git a/src/runtime/CL/functions/CLActivationLayer.cpp b/src/runtime/CL/functions/CLActivationLayer.cpp
index 4aeb3a15e1..2b66795cf9 100644
--- a/src/runtime/CL/functions/CLActivationLayer.cpp
+++ b/src/runtime/CL/functions/CLActivationLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018 ARM Limited.
+ * Copyright (c) 2016-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -27,7 +27,12 @@
#include "arm_compute/core/Types.h"
#include "support/ToolchainSupport.h"
-using namespace arm_compute;
+namespace arm_compute
+{
+CLActivationLayer::CLActivationLayer(void *ctx)
+{
+ ARM_COMPUTE_UNUSED(ctx);
+}
void CLActivationLayer::configure(ICLTensor *input, ICLTensor *output, ActivationLayerInfo act_info)
{
@@ -40,3 +45,4 @@ Status CLActivationLayer::validate(const ITensorInfo *input, const ITensorInfo *
{
return CLActivationLayerKernel::validate(input, output, act_info);
}
+} // namespace arm_compute
diff --git a/src/runtime/CPP/CPPScheduler.cpp b/src/runtime/CPP/CPPScheduler.cpp
index 5916bb46fd..9b670d5c04 100644
--- a/src/runtime/CPP/CPPScheduler.cpp
+++ b/src/runtime/CPP/CPPScheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018 ARM Limited.
+ * Copyright (c) 2016-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -32,6 +32,7 @@
#include <atomic>
#include <condition_variable>
#include <iostream>
+#include <list>
#include <mutex>
#include <system_error>
#include <thread>
@@ -90,7 +91,31 @@ void process_workloads(std::vector<IScheduler::Workload> &workloads, ThreadFeede
} //namespace
-class CPPScheduler::Thread
+struct CPPScheduler::Impl
+{
+ Impl(unsigned int thread_hint)
+ : _num_threads(thread_hint), _threads(_num_threads - 1)
+ {
+ }
+ void set_num_threads(unsigned int num_threads, unsigned int thead_hint)
+ {
+ _num_threads = num_threads == 0 ? thead_hint : num_threads;
+ _threads.resize(_num_threads - 1);
+ }
+ unsigned int num_threads() const
+ {
+ return _num_threads;
+ }
+
+ void run_workloads(std::vector<IScheduler::Workload> &workloads);
+
+ class Thread;
+
+ unsigned int _num_threads;
+ std::list<Thread> _threads;
+};
+
+class CPPScheduler::Impl::Thread
{
public:
/** Start a new thread. */
@@ -132,12 +157,12 @@ private:
std::exception_ptr _current_exception{ nullptr };
};
-CPPScheduler::Thread::Thread()
+CPPScheduler::Impl::Thread::Thread()
{
_thread = std::thread(&Thread::worker_thread, this);
}
-CPPScheduler::Thread::~Thread()
+CPPScheduler::Impl::Thread::~Thread()
{
// Make sure worker thread has ended
if(_thread.joinable())
@@ -148,7 +173,7 @@ CPPScheduler::Thread::~Thread()
}
}
-void CPPScheduler::Thread::start(std::vector<IScheduler::Workload> *workloads, ThreadFeeder &feeder, const ThreadInfo &info)
+void CPPScheduler::Impl::Thread::start(std::vector<IScheduler::Workload> *workloads, ThreadFeeder &feeder, const ThreadInfo &info)
{
_workloads = workloads;
_feeder = &feeder;
@@ -161,7 +186,7 @@ void CPPScheduler::Thread::start(std::vector<IScheduler::Workload> *workloads, T
_cv.notify_one();
}
-void CPPScheduler::Thread::wait()
+void CPPScheduler::Impl::Thread::wait()
{
{
std::unique_lock<std::mutex> lock(_m);
@@ -174,7 +199,7 @@ void CPPScheduler::Thread::wait()
}
}
-void CPPScheduler::Thread::worker_thread()
+void CPPScheduler::Impl::Thread::worker_thread()
{
while(true)
{
@@ -209,6 +234,9 @@ void CPPScheduler::Thread::worker_thread()
}
}
+/*
+ * This singleton has been deprecated and will be removed in the next release
+ */
CPPScheduler &CPPScheduler::get()
{
static CPPScheduler scheduler;
@@ -216,26 +244,26 @@ CPPScheduler &CPPScheduler::get()
}
CPPScheduler::CPPScheduler()
- : _num_threads(num_threads_hint()),
- _threads(_num_threads - 1)
+ : _impl(support::cpp14::make_unique<Impl>(num_threads_hint()))
{
}
+CPPScheduler::~CPPScheduler() = default;
+
void CPPScheduler::set_num_threads(unsigned int num_threads)
{
- _num_threads = num_threads == 0 ? num_threads_hint() : num_threads;
- _threads.resize(_num_threads - 1);
+ _impl->set_num_threads(num_threads, num_threads_hint());
}
unsigned int CPPScheduler::num_threads() const
{
- return _num_threads;
+ return _impl->num_threads();
}
#ifndef DOXYGEN_SKIP_THIS
void CPPScheduler::run_workloads(std::vector<IScheduler::Workload> &workloads)
{
- const unsigned int num_threads = std::min(_num_threads, static_cast<unsigned int>(workloads.size()));
+ const unsigned int num_threads = std::min(_impl->num_threads(), static_cast<unsigned int>(workloads.size()));
if(num_threads < 1)
{
return;
@@ -245,7 +273,7 @@ void CPPScheduler::run_workloads(std::vector<IScheduler::Workload> &workloads)
info.cpu_info = &_cpu_info;
info.num_threads = num_threads;
unsigned int t = 0;
- auto thread_it = _threads.begin();
+ auto thread_it = _impl->_threads.begin();
for(; t < num_threads - 1; ++t, ++thread_it)
{
info.thread_id = t;
@@ -258,7 +286,7 @@ void CPPScheduler::run_workloads(std::vector<IScheduler::Workload> &workloads)
try
{
#endif /* ARM_COMPUTE_EXCEPTIONS_DISABLED */
- for(auto &thread : _threads)
+ for(auto &thread : _impl->_threads)
{
thread.wait();
}
@@ -278,7 +306,7 @@ void CPPScheduler::schedule(ICPPKernel *kernel, const Hints &hints)
const Window &max_window = kernel->window();
const unsigned int num_iterations = max_window.num_iterations(hints.split_dimension());
- const unsigned int num_threads = std::min(num_iterations, _num_threads);
+ const unsigned int num_threads = std::min(num_iterations, _impl->_num_threads);
if(num_iterations == 0)
{
@@ -302,7 +330,7 @@ void CPPScheduler::schedule(ICPPKernel *kernel, const Hints &hints)
case StrategyHint::DYNAMIC:
{
// Make sure we don't use some windows which are too small as this might create some contention on the ThreadFeeder
- const unsigned int max_iterations = static_cast<unsigned int>(_num_threads) * 3;
+ const unsigned int max_iterations = static_cast<unsigned int>(_impl->_num_threads) * 3;
num_windows = num_iterations > max_iterations ? max_iterations : num_iterations;
break;
}
diff --git a/src/runtime/CPP/SingleThreadScheduler.cpp b/src/runtime/CPP/SingleThreadScheduler.cpp
index 37011595fd..152569fb67 100644
--- a/src/runtime/CPP/SingleThreadScheduler.cpp
+++ b/src/runtime/CPP/SingleThreadScheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,12 +29,6 @@
namespace arm_compute
{
-SingleThreadScheduler &SingleThreadScheduler::get()
-{
- static SingleThreadScheduler scheduler;
- return scheduler;
-}
-
void SingleThreadScheduler::set_num_threads(unsigned int num_threads)
{
ARM_COMPUTE_UNUSED(num_threads);
diff --git a/src/runtime/DeviceProperties.cpp b/src/runtime/DeviceProperties.cpp
new file mode 100644
index 0000000000..e88aa7124c
--- /dev/null
+++ b/src/runtime/DeviceProperties.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/runtime/DeviceProperties.h"
+
+#include "arm_compute/runtime/CPUUtils.h"
+
+namespace arm_compute
+{
+DeviceProperties::DeviceProperties()
+{
+ get_cpu_configuration(cpu_info);
+}
+} // namespace arm_compute
diff --git a/src/runtime/GLES_COMPUTE/functions/GCActivationLayer.cpp b/src/runtime/GLES_COMPUTE/functions/GCActivationLayer.cpp
index 8686416616..207e8cef56 100644
--- a/src/runtime/GLES_COMPUTE/functions/GCActivationLayer.cpp
+++ b/src/runtime/GLES_COMPUTE/functions/GCActivationLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -27,7 +27,12 @@
#include "arm_compute/core/Helpers.h"
#include "support/ToolchainSupport.h"
-using namespace arm_compute;
+namespace arm_compute
+{
+GCActivationLayer::GCActivationLayer(void *ctx)
+{
+ ARM_COMPUTE_UNUSED(ctx);
+}
void GCActivationLayer::configure(IGCTensor *input, IGCTensor *output, ActivationLayerInfo act_info)
{
@@ -35,3 +40,4 @@ void GCActivationLayer::configure(IGCTensor *input, IGCTensor *output, Activatio
k->configure(input, output, act_info);
_kernel = std::move(k);
}
+} // namespace arm_compute
diff --git a/src/runtime/NEON/INESimpleFunctionNoBorder.cpp b/src/runtime/NEON/INESimpleFunctionNoBorder.cpp
index 12872048c7..2cabee4c46 100644
--- a/src/runtime/NEON/INESimpleFunctionNoBorder.cpp
+++ b/src/runtime/NEON/INESimpleFunctionNoBorder.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018 ARM Limited.
+ * Copyright (c) 2018-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,16 +24,18 @@
#include "arm_compute/runtime/NEON/INESimpleFunctionNoBorder.h"
#include "arm_compute/runtime/NEON/NEScheduler.h"
+#include "arm_compute/runtime/Utils.h"
namespace arm_compute
{
-INESimpleFunctionNoBorder::INESimpleFunctionNoBorder() // NOLINT
- : _kernel()
+INESimpleFunctionNoBorder::INESimpleFunctionNoBorder(IRuntimeContext *ctx)
+ : _kernel(),
+ _ctx(ctx)
{
}
void INESimpleFunctionNoBorder::run()
{
- NEScheduler::get().schedule(_kernel.get(), Window::DimY);
+ schedule_kernel_on_ctx(_ctx, _kernel.get(), Window::DimY);
}
} // namespace arm_compute
diff --git a/src/runtime/NEON/functions/NEActivationLayer.cpp b/src/runtime/NEON/functions/NEActivationLayer.cpp
index 6af71a3580..1b8651487d 100644
--- a/src/runtime/NEON/functions/NEActivationLayer.cpp
+++ b/src/runtime/NEON/functions/NEActivationLayer.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,10 +24,15 @@
#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h"
#include "arm_compute/core/NEON/kernels/NEActivationLayerKernel.h"
+#include "arm_compute/runtime/IRuntimeContext.h"
#include "support/ToolchainSupport.h"
-using namespace arm_compute;
-
+namespace arm_compute
+{
+NEActivationLayer::NEActivationLayer(IRuntimeContext *ctx) // NOLINT
+ : INESimpleFunctionNoBorder(ctx)
+{
+}
void NEActivationLayer::configure(ITensor *input, ITensor *output, ActivationLayerInfo activation_info)
{
auto k = arm_compute::support::cpp14::make_unique<NEActivationLayerKernel>();
@@ -39,3 +44,4 @@ Status NEActivationLayer::validate(const ITensorInfo *input, const ITensorInfo *
{
return NEActivationLayerKernel::validate(input, output, act_info);
}
+} // namespace arm_compute
diff --git a/src/runtime/OMP/OMPScheduler.cpp b/src/runtime/OMP/OMPScheduler.cpp
index 2355389dbd..f67f06fc94 100644
--- a/src/runtime/OMP/OMPScheduler.cpp
+++ b/src/runtime/OMP/OMPScheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -31,14 +31,8 @@
#include <omp.h>
-using namespace arm_compute;
-
-OMPScheduler &OMPScheduler::get()
+namespace arm_compute
{
- static OMPScheduler scheduler;
- return scheduler;
-}
-
OMPScheduler::OMPScheduler() // NOLINT
: _num_threads(omp_get_max_threads())
{
@@ -109,3 +103,4 @@ void OMPScheduler::run_workloads(std::vector<arm_compute::IScheduler::Workload>
}
}
#endif /* DOXYGEN_SKIP_THIS */
+} // namespace arm_compute
diff --git a/src/runtime/RuntimeContext.cpp b/src/runtime/RuntimeContext.cpp
new file mode 100644
index 0000000000..308e2788a9
--- /dev/null
+++ b/src/runtime/RuntimeContext.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/runtime/RuntimeContext.h"
+
+#include "arm_compute/core/Validate.h"
+#include "arm_compute/runtime/SchedulerFactory.h"
+
+namespace arm_compute
+{
+RuntimeContext::RuntimeContext()
+ : _owned_scheduler(SchedulerFactory::create()), _scheduler(_owned_scheduler.get()), _device_props()
+{
+}
+
+void RuntimeContext::set_scheduler(IScheduler *scheduler)
+{
+ ARM_COMPUTE_ERROR_ON_NULLPTR(scheduler);
+ _scheduler = scheduler;
+}
+
+IScheduler *RuntimeContext::scheduler()
+{
+ return _scheduler;
+}
+
+IAssetManager *RuntimeContext::asset_manager()
+{
+ return nullptr;
+}
+
+const DeviceProperties &RuntimeContext::properties()
+{
+ return _device_props;
+}
+} // namespace arm_compute
diff --git a/src/runtime/Scheduler.cpp b/src/runtime/Scheduler.cpp
index 8925acfa47..1af39d8122 100644
--- a/src/runtime/Scheduler.cpp
+++ b/src/runtime/Scheduler.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -24,6 +24,8 @@
#include "arm_compute/runtime/Scheduler.h"
#include "arm_compute/core/Error.h"
+#include "support/ToolchainSupport.h"
+
#if ARM_COMPUTE_CPP_SCHEDULER
#include "arm_compute/runtime/CPP/CPPScheduler.h"
#endif /* ARM_COMPUTE_CPP_SCHEDULER */
@@ -46,6 +48,27 @@ Scheduler::Type Scheduler::_scheduler_type = Scheduler::Type::CPP;
Scheduler::Type Scheduler::_scheduler_type = Scheduler::Type::ST;
#endif /* ARM_COMPUTE_*_SCHEDULER */
+std::shared_ptr<IScheduler> Scheduler::_custom_scheduler = nullptr;
+
+namespace
+{
+std::map<Scheduler::Type, std::unique_ptr<IScheduler>> init()
+{
+ std::map<Scheduler::Type, std::unique_ptr<IScheduler>> m;
+ m[Scheduler::Type::ST] = support::cpp14::make_unique<SingleThreadScheduler>();
+#if defined(ARM_COMPUTE_CPP_SCHEDULER)
+ m[Scheduler::Type::CPP] = support::cpp14::make_unique<CPPScheduler>();
+#endif // defined(ARM_COMPUTE_CPP_SCHEDULER)
+#if defined(ARM_COMPUTE_OPENMP_SCHEDULER)
+ m[Scheduler::Type::OMP] = support::cpp14::make_unique<OMPScheduler>();
+#endif // defined(ARM_COMPUTE_OPENMP_SCHEDULER)
+
+ return m;
+}
+} // namespace
+
+std::map<Scheduler::Type, std::unique_ptr<IScheduler>> Scheduler::_schedulers = init();
+
void Scheduler::set(Type t)
{
ARM_COMPUTE_ERROR_ON(!Scheduler::is_available(t));
@@ -54,37 +77,13 @@ void Scheduler::set(Type t)
bool Scheduler::is_available(Type t)
{
- switch(t)
+ if(t == Type::CUSTOM)
{
- case Type::ST:
- {
- return true;
- }
- case Type::CPP:
- {
-#if ARM_COMPUTE_CPP_SCHEDULER
- return true;
-#else /* ARM_COMPUTE_CPP_SCHEDULER */
- return false;
-#endif /* ARM_COMPUTE_CPP_SCHEDULER */
- }
- case Type::OMP:
- {
-#if ARM_COMPUTE_OPENMP_SCHEDULER
- return true;
-#else /* ARM_COMPUTE_OPENMP_SCHEDULER */
- return false;
-#endif /* ARM_COMPUTE_OPENMP_SCHEDULER */
- }
- case Type::CUSTOM:
- {
- return _custom_scheduler != nullptr;
- }
- default:
- {
- ARM_COMPUTE_ERROR("Invalid Scheduler type");
- return false;
- }
+ return _custom_scheduler != nullptr;
+ }
+ else
+ {
+ return _schedulers.find(t) != _schedulers.end();
}
}
@@ -95,53 +94,31 @@ Scheduler::Type Scheduler::get_type()
IScheduler &Scheduler::get()
{
- switch(_scheduler_type)
+ if(_scheduler_type == Type::CUSTOM)
{
- case Type::ST:
- {
- return SingleThreadScheduler::get();
- }
- case Type::CPP:
+ if(_custom_scheduler == nullptr)
{
-#if ARM_COMPUTE_CPP_SCHEDULER
- return CPPScheduler::get();
-#else /* ARM_COMPUTE_CPP_SCHEDULER */
- ARM_COMPUTE_ERROR("Recompile with cppthreads=1 to use C++11 scheduler.");
-#endif /* ARM_COMPUTE_CPP_SCHEDULER */
- break;
+ ARM_COMPUTE_ERROR("No custom scheduler has been setup. Call set(std::shared_ptr<IScheduler> &scheduler) before Scheduler::get()");
}
- case Type::OMP:
+ else
{
-#if ARM_COMPUTE_OPENMP_SCHEDULER
- return OMPScheduler::get();
-#else /* ARM_COMPUTE_OPENMP_SCHEDULER */
- ARM_COMPUTE_ERROR("Recompile with openmp=1 to use openmp scheduler.");
-#endif /* ARM_COMPUTE_OPENMP_SCHEDULER */
- break;
+ return *_custom_scheduler;
}
- case Type::CUSTOM:
+ }
+ else
+ {
+ auto it = _schedulers.find(_scheduler_type);
+ if(it != _schedulers.end())
{
- if(_custom_scheduler == nullptr)
- {
- ARM_COMPUTE_ERROR("No custom scheduler has been setup. Call set(std::shared_ptr<IScheduler> &scheduler) before Scheduler::get()");
- }
- else
- {
- return *_custom_scheduler;
- }
- break;
+ return *it->second;
}
- default:
+ else
{
ARM_COMPUTE_ERROR("Invalid Scheduler type");
- break;
}
}
- return SingleThreadScheduler::get();
}
-std::shared_ptr<IScheduler> Scheduler::_custom_scheduler = nullptr;
-
void Scheduler::set(std::shared_ptr<IScheduler> scheduler)
{
_custom_scheduler = std::move(scheduler);
diff --git a/src/runtime/SchedulerFactory.cpp b/src/runtime/SchedulerFactory.cpp
new file mode 100644
index 0000000000..8bdd510367
--- /dev/null
+++ b/src/runtime/SchedulerFactory.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/runtime/SchedulerFactory.h"
+
+#include "support/ToolchainSupport.h"
+
+#include "arm_compute/core/Error.h"
+#if ARM_COMPUTE_CPP_SCHEDULER
+#include "arm_compute/runtime/CPP/CPPScheduler.h"
+#endif /* ARM_COMPUTE_CPP_SCHEDULER */
+
+#include "arm_compute/runtime/SingleThreadScheduler.h"
+
+#if ARM_COMPUTE_OPENMP_SCHEDULER
+#include "arm_compute/runtime/OMP/OMPScheduler.h"
+#endif /* ARM_COMPUTE_OPENMP_SCHEDULER */
+
+namespace arm_compute
+{
+#if !ARM_COMPUTE_CPP_SCHEDULER && ARM_COMPUTE_OPENMP_SCHEDULER
+const SchedulerFactory::Type SchedulerFactory::_default_type = SchedulerFactory::Type::OMP;
+#elif ARM_COMPUTE_CPP_SCHEDULER && !ARM_COMPUTE_OPENMP_SCHEDULER
+const SchedulerFactory::Type SchedulerFactory::_default_type = SchedulerFactory::Type::CPP;
+#elif ARM_COMPUTE_CPP_SCHEDULER && ARM_COMPUTE_OPENMP_SCHEDULER
+const SchedulerFactory::Type SchedulerFactory::_default_type = SchedulerFactory::Type::CPP;
+#else /* ARM_COMPUTE_*_SCHEDULER */
+const SchedulerFactory::Type SchedulerFactory::_default_type = SchedulerFactory::Type::ST;
+#endif /* ARM_COMPUTE_*_SCHEDULER */
+
+std::unique_ptr<IScheduler> SchedulerFactory::create(Type type)
+{
+ switch(type)
+ {
+ case Type::ST:
+ {
+ return support::cpp14::make_unique<SingleThreadScheduler>();
+ }
+ case Type::CPP:
+ {
+#if ARM_COMPUTE_CPP_SCHEDULER
+ return support::cpp14::make_unique<CPPScheduler>();
+#else /* ARM_COMPUTE_CPP_SCHEDULER */
+ ARM_COMPUTE_ERROR("Recompile with cppthreads=1 to use C++11 scheduler.");
+#endif /* ARM_COMPUTE_CPP_SCHEDULER */
+ }
+ case Type::OMP:
+ {
+#if ARM_COMPUTE_OPENMP_SCHEDULER
+ return support::cpp14::make_unique<OMPScheduler>();
+#else /* ARM_COMPUTE_OPENMP_SCHEDULER */
+ ARM_COMPUTE_ERROR("Recompile with openmp=1 to use openmp scheduler.");
+#endif /* ARM_COMPUTE_OPENMP_SCHEDULER */
+ }
+ default:
+ {
+ ARM_COMPUTE_ERROR("Invalid Scheduler type");
+ break;
+ }
+ }
+}
+} // namespace arm_compute
diff --git a/src/runtime/Utils.cpp b/src/runtime/Utils.cpp
index 81de782399..70494be05c 100644
--- a/src/runtime/Utils.cpp
+++ b/src/runtime/Utils.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -23,16 +23,20 @@
*/
#include "arm_compute/runtime/Utils.h"
+#include "arm_compute/runtime/NEON/NEScheduler.h"
+
#include <map>
#include <string>
-using namespace arm_compute;
-
+namespace arm_compute
+{
+#ifndef DOXYGEN_SKIP_THIS
static const std::string information =
#include "arm_compute_version.embed"
;
+#endif /* DOXYGEN_SKIP_THIS */
-const std::string &arm_compute::string_from_scheduler_type(Scheduler::Type t)
+const std::string &string_from_scheduler_type(Scheduler::Type t)
{
static std::map<Scheduler::Type, const std::string> scheduler_type_map =
{
@@ -44,3 +48,17 @@ const std::string &arm_compute::string_from_scheduler_type(Scheduler::Type t)
return scheduler_type_map[t];
}
+
+void schedule_kernel_on_ctx(IRuntimeContext *ctx, ICPPKernel *kernel, const IScheduler::Hints &hints)
+{
+ if(ctx)
+ {
+ ARM_COMPUTE_ERROR_ON(ctx->scheduler() == nullptr);
+ ctx->scheduler()->schedule(kernel, hints);
+ }
+ else
+ {
+ NEScheduler::get().schedule(kernel, hints);
+ }
+}
+} // namespace arm_compute
diff --git a/tests/Globals.h b/tests/Globals.h
index c4c450c5fe..569b1a31c6 100644
--- a/tests/Globals.h
+++ b/tests/Globals.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -25,6 +25,7 @@
#define __ARM_COMPUTE_TEST_GLOBALS_H__
#include "tests/AssetsLibrary.h"
+#include "tests/ParametersLibrary.h"
#include <memory>
@@ -32,7 +33,8 @@ namespace arm_compute
{
namespace test
{
-extern std::unique_ptr<AssetsLibrary> library;
+extern std::unique_ptr<AssetsLibrary> library;
+extern std::unique_ptr<ParametersLibrary> parameters;
} // namespace test
} // namespace arm_compute
#endif /* __ARM_COMPUTE_TEST_GLOBALS_H__ */
diff --git a/tests/ParametersLibrary.cpp b/tests/ParametersLibrary.cpp
new file mode 100644
index 0000000000..16152c8482
--- /dev/null
+++ b/tests/ParametersLibrary.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "tests/ParametersLibrary.h"
+
+namespace arm_compute
+{
+namespace test
+{
+void ParametersLibrary::set_cpu_ctx(std::unique_ptr<IRuntimeContext> cpu_ctx)
+{
+ _cpu_ctx = std::move(cpu_ctx);
+}
+
+template <>
+typename ContextType<Tensor>::type *ParametersLibrary::get_ctx<Tensor>()
+{
+ return _cpu_ctx.get();
+}
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/ParametersLibrary.h b/tests/ParametersLibrary.h
new file mode 100644
index 0000000000..a99be46d3f
--- /dev/null
+++ b/tests/ParametersLibrary.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_PARAMETERS_LIBRARY_H__
+#define __ARM_COMPUTE_TEST_PARAMETERS_LIBRARY_H__
+
+#include "arm_compute/runtime/IRuntimeContext.h"
+#include "arm_compute/runtime/Tensor.h"
+
+#include <memory>
+
+namespace arm_compute
+{
+namespace test
+{
+// Return type trait helper
+template <class T>
+struct ContextType
+{
+ using type = void;
+};
+template <>
+struct ContextType<Tensor>
+{
+ using type = IRuntimeContext;
+};
+
+/** Class that contains all the global parameters used by the tests */
+class ParametersLibrary final
+{
+public:
+ /** Default constructor */
+ ParametersLibrary() = default;
+ /** Set cpu context to be used by the tests
+ *
+ * @param[in] cpu_ctx CPU context to use
+ */
+ void set_cpu_ctx(std::unique_ptr<IRuntimeContext> cpu_ctx);
+ /** Get context given a tensor type
+ *
+ * @tparam TensorType
+ *
+ * @return Pointer to the context
+ */
+ template <typename TensorType>
+ typename ContextType<TensorType>::type *get_ctx()
+ {
+ return nullptr;
+ }
+
+private:
+ std::unique_ptr<IRuntimeContext> _cpu_ctx{ nullptr };
+};
+} // namespace test
+} // namespace arm_compute
+#endif //__ARM_COMPUTE_TEST_PARAMETERS_LIBRARY_H__
diff --git a/tests/Utils.h b/tests/Utils.h
index f88b01dc40..f26507d1a0 100644
--- a/tests/Utils.h
+++ b/tests/Utils.h
@@ -54,6 +54,9 @@
#include <type_traits>
#include <vector>
+#include "arm_compute/runtime/CPP/CPPScheduler.h"
+#include "arm_compute/runtime/RuntimeContext.h"
+
namespace arm_compute
{
#ifdef ARM_COMPUTE_CL
diff --git a/tests/benchmark/fixtures/ActivationLayerFixture.h b/tests/benchmark/fixtures/ActivationLayerFixture.h
index a82861f624..2ac10b2746 100644
--- a/tests/benchmark/fixtures/ActivationLayerFixture.h
+++ b/tests/benchmark/fixtures/ActivationLayerFixture.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -41,6 +41,11 @@ template <typename TensorType, typename Function, typename Accessor>
class ActivationLayerFixture : public framework::Fixture
{
public:
+ ActivationLayerFixture()
+ : src(), dst(), act_layer(parameters->get_ctx<TensorType>())
+ {
+ }
+
template <typename...>
void setup(TensorShape shape, ActivationLayerInfo info, DataType data_type, int batches)
{
@@ -78,9 +83,9 @@ public:
}
private:
- TensorType src{};
- TensorType dst{};
- Function act_layer{};
+ TensorType src;
+ TensorType dst;
+ Function act_layer;
};
} // namespace benchmark
} // namespace test
diff --git a/tests/framework/Framework.cpp b/tests/framework/Framework.cpp
index cc7852906c..fbc2456047 100644
--- a/tests/framework/Framework.cpp
+++ b/tests/framework/Framework.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -40,6 +40,8 @@ namespace test
{
namespace framework
{
+std::unique_ptr<InstrumentsInfo> instruments_info;
+
Framework::Framework()
{
_available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::WALL_CLOCK_TIMESTAMPS, ScaleFactor::NONE), Instrument::make_instrument<WallClockTimestamps, ScaleFactor::NONE>);
@@ -83,6 +85,8 @@ Framework::Framework()
_available_instruments.emplace(std::pair<InstrumentType, ScaleFactor>(InstrumentType::OPENCL_MEMORY_USAGE, ScaleFactor::SCALE_1M),
Instrument::make_instrument<OpenCLMemoryUsage, ScaleFactor::SCALE_1M>);
#endif /* ARM_COMPUTE_CL */
+
+ instruments_info = support::cpp14::make_unique<InstrumentsInfo>();
}
std::set<InstrumentsDescription> Framework::available_instruments() const
@@ -679,6 +683,12 @@ LogLevel Framework::log_level() const
{
return _log_level;
}
+
+void Framework::set_instruments_info(InstrumentsInfo instr_info)
+{
+ ARM_COMPUTE_ERROR_ON(instruments_info == nullptr);
+ *instruments_info = instr_info;
+}
} // namespace framework
} // namespace test
} // namespace arm_compute
diff --git a/tests/framework/Framework.h b/tests/framework/Framework.h
index 65ffc0a818..c02416f9b5 100644
--- a/tests/framework/Framework.h
+++ b/tests/framework/Framework.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -293,6 +293,13 @@ public:
* @return The current logging level.
*/
LogLevel log_level() const;
+ /** Sets instruments info
+ *
+ * @note TODO(COMPMID-2638) : Remove once instruments are transferred outside the framework.
+ *
+ * @param[in] instr_info Instruments info to set
+ */
+ void set_instruments_info(InstrumentsInfo instr_info);
private:
Framework();
diff --git a/tests/framework/instruments/Instruments.h b/tests/framework/instruments/Instruments.h
index 370db8d4dc..8adf501c18 100644
--- a/tests/framework/instruments/Instruments.h
+++ b/tests/framework/instruments/Instruments.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -33,6 +33,7 @@
#include "SchedulerTimer.h"
#include "WallClockTimer.h"
+#include <memory>
#include <sstream>
#include <string>
@@ -59,6 +60,12 @@ enum class InstrumentType : unsigned int
SCHEDULER_TIMESTAMPS = 0x0900,
};
+struct InstrumentsInfo
+{
+ std::vector<ISchedulerUser *> _scheduler_users{};
+};
+extern std::unique_ptr<InstrumentsInfo> instruments_info;
+
using InstrumentsDescription = std::pair<InstrumentType, ScaleFactor>;
InstrumentsDescription instrument_type_from_name(const std::string &name);
diff --git a/tests/framework/instruments/SchedulerTimer.cpp b/tests/framework/instruments/SchedulerTimer.cpp
index c114dfbd9d..98c9b878d9 100644
--- a/tests/framework/instruments/SchedulerTimer.cpp
+++ b/tests/framework/instruments/SchedulerTimer.cpp
@@ -23,6 +23,7 @@
*/
#include "SchedulerTimer.h"
+#include "Instruments.h"
#include "WallClockTimer.h"
#include "arm_compute/core/CPP/ICPPKernel.h"
#include "arm_compute/core/utils/misc/Cast.h"
@@ -114,8 +115,12 @@ private:
template <bool output_timestamps>
SchedulerClock<output_timestamps>::SchedulerClock(ScaleFactor scale_factor)
- : _kernels(), _real_scheduler(nullptr), _real_scheduler_type(), _real_graph_function(nullptr), _scale_factor(scale_factor), _interceptor(nullptr)
+ : _kernels(), _real_scheduler(nullptr), _real_scheduler_type(), _real_graph_function(nullptr), _scale_factor(scale_factor), _interceptor(nullptr), _scheduler_users()
{
+ if(instruments_info != nullptr)
+ {
+ _scheduler_users = instruments_info->_scheduler_users;
+ }
}
template <bool output_timestamps>
@@ -157,6 +162,17 @@ void SchedulerClock<output_timestamps>::test_start()
_interceptor = std::make_shared<Interceptor<output_timestamps>>(_kernels, *_real_scheduler, _scale_factor);
Scheduler::set(std::static_pointer_cast<IScheduler>(_interceptor));
graph::TaskExecutor::get().execute_function = task_interceptor;
+
+ // Create an interceptor for each scheduler
+ // TODO(COMPID-2638) : Allow multiple schedulers, now it assumes the same scheduler is used.
+ std::for_each(std::begin(_scheduler_users), std::end(_scheduler_users),
+ [&](ISchedulerUser * user)
+ {
+ if(user != nullptr && user->scheduler() != nullptr)
+ {
+ user->intercept_scheduler(support::cpp14::make_unique<Interceptor<output_timestamps>>(_kernels, *user->scheduler(), _scale_factor));
+ }
+ });
}
}
@@ -175,6 +191,16 @@ void SchedulerClock<output_timestamps>::test_stop()
_interceptor = nullptr;
graph::TaskExecutor::get().execute_function = _real_graph_function;
_real_graph_function = nullptr;
+
+ // Restore schedulers
+ std::for_each(std::begin(_scheduler_users), std::end(_scheduler_users),
+ [&](ISchedulerUser * user)
+ {
+ if(user != nullptr)
+ {
+ user->restore_scheduler();
+ }
+ });
}
template <bool output_timestamps>
diff --git a/tests/framework/instruments/SchedulerTimer.h b/tests/framework/instruments/SchedulerTimer.h
index 64adb488ae..ea64b227eb 100644
--- a/tests/framework/instruments/SchedulerTimer.h
+++ b/tests/framework/instruments/SchedulerTimer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018 ARM Limited.
+ * Copyright (c) 2017-2019 ARM Limited.
*
* SPDX-License-Identifier: MIT
*
@@ -29,6 +29,8 @@
#include "arm_compute/runtime/Scheduler.h"
#include <list>
+#include <memory>
+#include <vector>
namespace arm_compute
{
@@ -36,6 +38,26 @@ namespace test
{
namespace framework
{
+/** Scheduler user interface */
+class ISchedulerUser
+{
+public:
+ /** Default Destructor */
+ virtual ~ISchedulerUser() = default;
+ /** Intercept the scheduler used by
+ *
+ * @param interceptor Intercept the scheduler used by the scheduler user.
+ */
+ virtual void intercept_scheduler(std::unique_ptr<IScheduler> interceptor) = 0;
+ /** Restore the original scheduler */
+ virtual void restore_scheduler() = 0;
+ /** Real scheduler accessor
+ *
+ * @return The real scheduler
+ */
+ virtual IScheduler *scheduler() = 0;
+};
+
/** Instrument creating measurements based on the information returned by clGetEventProfilingInfo for each OpenCL kernel executed*/
template <bool output_timestamps>
class SchedulerClock : public Instrument
@@ -46,7 +68,6 @@ public:
* @param[in] scale_factor Measurement scale factor.
*/
SchedulerClock(ScaleFactor scale_factor);
-
/** Prevent instances of this class from being copy constructed */
SchedulerClock(const SchedulerClock &) = delete;
/** Prevent instances of this class from being copied */
@@ -58,6 +79,7 @@ public:
/** Use the default destructor */
~SchedulerClock() = default;
+ // Inherited overridden methods
std::string id() const override;
void test_start() override;
void start() override;
@@ -79,6 +101,7 @@ private:
std::function<decltype(graph::execute_task)> _real_graph_function;
ScaleFactor _scale_factor;
std::shared_ptr<IScheduler> _interceptor;
+ std::vector<ISchedulerUser *> _scheduler_users;
};
using SchedulerTimer = SchedulerClock<false>;
diff --git a/tests/instruments/Helpers.h b/tests/instruments/Helpers.h
new file mode 100644
index 0000000000..07387f10f8
--- /dev/null
+++ b/tests/instruments/Helpers.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef __ARM_COMPUTE_TEST_INSTRUMENTS_UTILS_H__
+#define __ARM_COMPUTE_TEST_INSTRUMENTS_UTILS_H__
+
+#include "arm_compute/runtime/RuntimeContext.h"
+#include "tests/framework/instruments/Instruments.h"
+
+namespace arm_compute
+{
+namespace test
+{
+class ContextSchedulerUser : public framework::ISchedulerUser
+{
+public:
+ /** Default Constructor
+ *
+ * @param[in] ctx Runtime context to track
+ */
+ ContextSchedulerUser(RuntimeContext *ctx)
+ : _ctx(ctx), _scheduler_to_use(nullptr), _real_scheduler(nullptr), _interceptor(nullptr)
+ {
+ ARM_COMPUTE_ERROR_ON(ctx == nullptr);
+ _real_scheduler = _ctx->scheduler();
+ _scheduler_to_use = _real_scheduler;
+ }
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ ContextSchedulerUser(const ContextSchedulerUser &) = delete;
+ /** Default move constructor */
+ ContextSchedulerUser(ContextSchedulerUser &&) = default;
+ /** Prevent instances of this class from being copied (As this class contains pointers) */
+ ContextSchedulerUser &operator=(const ContextSchedulerUser &) = delete;
+ /** Default move assignment operator */
+ ContextSchedulerUser &operator=(ContextSchedulerUser &&) = default;
+
+ // Overridden inherited methods
+ void intercept_scheduler(std::unique_ptr<IScheduler> interceptor)
+ {
+ if(interceptor != nullptr)
+ {
+ _interceptor = std::move(interceptor);
+ _scheduler_to_use = _interceptor.get();
+ _ctx->set_scheduler(_scheduler_to_use);
+ }
+ }
+ void restore_scheduler()
+ {
+ _interceptor = nullptr;
+ _scheduler_to_use = _real_scheduler;
+ _ctx->set_scheduler(_scheduler_to_use);
+ }
+ IScheduler *scheduler()
+ {
+ return _real_scheduler;
+ }
+
+private:
+ RuntimeContext *_ctx;
+ IScheduler *_scheduler_to_use;
+ IScheduler *_real_scheduler;
+ std::unique_ptr<IScheduler> _interceptor;
+};
+} // namespace test
+} // namespace arm_compute
+#endif /* __ARM_COMPUTE_TEST_INSTRUMENTS_UTILS_H__ */
diff --git a/tests/main.cpp b/tests/main.cpp
index 9690eb9a00..01741939a0 100644
--- a/tests/main.cpp
+++ b/tests/main.cpp
@@ -23,6 +23,7 @@
*/
#include "support/ToolchainSupport.h"
#include "tests/AssetsLibrary.h"
+#include "tests/ParametersLibrary.h"
#include "tests/framework/DatasetModes.h"
#include "tests/framework/Exceptions.h"
#include "tests/framework/Framework.h"
@@ -31,6 +32,7 @@
#include "tests/framework/command_line/CommonOptions.h"
#include "tests/framework/instruments/Instruments.h"
#include "tests/framework/printers/Printers.h"
+#include "tests/instruments/Helpers.h"
#include "utils/command_line/CommandLineOptions.h"
#include "utils/command_line/CommandLineParser.h"
@@ -72,7 +74,8 @@ namespace arm_compute
{
namespace test
{
-std::unique_ptr<AssetsLibrary> library;
+std::unique_ptr<AssetsLibrary> library;
+std::unique_ptr<ParametersLibrary> parameters;
} // namespace test
} // namespace arm_compute
@@ -167,7 +170,20 @@ int main(int argc, char **argv)
std::vector<std::unique_ptr<framework::Printer>> printers = options.create_printers();
+ // Setup CPU Scheduler
Scheduler::get().set_num_threads(threads->value());
+
+ // Create CPU context
+ auto cpu_ctx = support::cpp14::make_unique<RuntimeContext>();
+ cpu_ctx->set_scheduler(&Scheduler::get());
+
+ // Track CPU context
+ auto cpu_ctx_track = support::cpp14::make_unique<ContextSchedulerUser>(cpu_ctx.get());
+
+ // Create parameters
+ parameters = support::cpp14::make_unique<ParametersLibrary>();
+ parameters->set_cpu_ctx(std::move(cpu_ctx));
+
#ifdef ARM_COMPUTE_CL
if(enable_tuner->is_set())
{
@@ -232,7 +248,19 @@ int main(int argc, char **argv)
}
}
- framework.init(options.instruments->value(), options.iterations->value(), dataset_mode->value(), filter->value(), filter_id->value(), options.log_level->value());
+ // Setup instruments meta-data
+ framework::InstrumentsInfo instruments_info;
+ instruments_info._scheduler_users.push_back(cpu_ctx_track.get());
+ framework.set_instruments_info(instruments_info);
+
+ // Initialize framework
+ framework.init(options.instruments->value(),
+ options.iterations->value(),
+ dataset_mode->value(),
+ filter->value(),
+ filter_id->value(),
+ options.log_level->value());
+
for(auto &p : printers)
{
framework.add_printer(p.get());
diff --git a/tests/validation/CL/ActivationLayer.cpp b/tests/validation/CL/ActivationLayer.cpp
index e97f12f5a3..250777d541 100644
--- a/tests/validation/CL/ActivationLayer.cpp
+++ b/tests/validation/CL/ActivationLayer.cpp
@@ -25,6 +25,7 @@
#include "arm_compute/runtime/CL/CLTensor.h"
#include "arm_compute/runtime/CL/CLTensorAllocator.h"
#include "arm_compute/runtime/CL/functions/CLActivationLayer.h"
+#include "arm_compute/runtime/RuntimeContext.h"
#include "tests/CL/CLAccessor.h"
#include "tests/PaddingCalculator.h"
#include "tests/datasets/ActivationFunctionsDataset.h"
diff --git a/tests/validation/NEON/ActivationLayer.cpp b/tests/validation/NEON/ActivationLayer.cpp
index eb3a37fba7..8c18d47da9 100644
--- a/tests/validation/NEON/ActivationLayer.cpp
+++ b/tests/validation/NEON/ActivationLayer.cpp
@@ -23,6 +23,7 @@
*/
#include "arm_compute/core/Types.h"
#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h"
+#include "arm_compute/runtime/RuntimeContext.h"
#include "arm_compute/runtime/Tensor.h"
#include "arm_compute/runtime/TensorAllocator.h"
#include "tests/NEON/Accessor.h"
@@ -133,8 +134,11 @@ DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(datas
ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+ // Create context
+ RuntimeContext ctx;
+
// Create and configure function
- NEActivationLayer act_layer;
+ NEActivationLayer act_layer(&ctx);
if(in_place)
{
diff --git a/tests/validation/NEON/UNIT/RuntimeContext.cpp b/tests/validation/NEON/UNIT/RuntimeContext.cpp
new file mode 100644
index 0000000000..05670a94e8
--- /dev/null
+++ b/tests/validation/NEON/UNIT/RuntimeContext.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2019 ARM Limited.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include "arm_compute/runtime/RuntimeContext.h"
+
+#include "arm_compute/runtime/CPP/CPPScheduler.h"
+#include "arm_compute/runtime/NEON/functions/NEActivationLayer.h"
+#include "arm_compute/runtime/Tensor.h"
+#include "support/ToolchainSupport.h"
+#include "tests/Globals.h"
+#include "tests/NEON/Accessor.h"
+#include "tests/Utils.h"
+#include "tests/framework/Asserts.h"
+#include "tests/framework/Macros.h"
+#include "tests/validation/Validation.h"
+#include "tests/validation/reference/ActivationLayer.h"
+
+#include <memory>
+#include <random>
+#if !defined(BARE_METAL)
+#include <thread>
+#endif // !defined(BARE_METAL)
+
+namespace arm_compute
+{
+namespace test
+{
+namespace validation
+{
+TEST_SUITE(NEON)
+TEST_SUITE(UNIT)
+TEST_SUITE(RuntimeContext)
+
+TEST_CASE(Scheduler, framework::DatasetMode::ALL)
+{
+ using namespace arm_compute;
+ // Create a runtime context object
+ RuntimeContext ctx;
+
+ // Check if it's been initialised properly
+ ARM_COMPUTE_EXPECT(ctx.scheduler() != nullptr, framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(ctx.asset_manager() == nullptr, framework::LogLevel::ERRORS);
+
+ // Create a CPPScheduler
+ CPPScheduler scheduler;
+ ctx.set_scheduler(&scheduler);
+ // Check if the scheduler has been properly setup
+ ARM_COMPUTE_EXPECT(ctx.scheduler() != nullptr, framework::LogLevel::ERRORS);
+
+ // Create a new activation function
+ NEActivationLayer act_layer(&ctx);
+
+ Tensor src = create_tensor<Tensor>(TensorShape(32, 32), DataType::F32, 1);
+ Tensor dst = create_tensor<Tensor>(TensorShape(32, 32), DataType::F32, 1);
+
+ act_layer.configure(&src, &dst, ActivationLayerInfo(ActivationLayerInfo::ActivationFunction::LINEAR));
+
+ ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Allocate tensors
+ src.allocator()->allocate();
+ dst.allocator()->allocate();
+
+ ARM_COMPUTE_EXPECT(!src.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ float min_bound = 0;
+ float max_bound = 0;
+ std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<float>(ActivationLayerInfo::ActivationFunction::LINEAR, DataType::F32);
+ std::uniform_real_distribution<> distribution(min_bound, max_bound);
+ library->fill(Accessor(src), distribution, 0);
+
+ // Compute function
+ act_layer.run();
+}
+
+#if !defined(BARE_METAL)
+// This test tries scheduling work concurrently from two independent threads
+TEST_CASE(MultipleThreadedScheduller, framework::DatasetMode::ALL)
+{
+ // Create a runtime context object for thread 1
+ RuntimeContext ctx1;
+
+ // Create a runtime context object for thread 2
+ RuntimeContext ctx2;
+
+ // Create a new activation function
+ NEActivationLayer act_layer_thread0(&ctx1);
+ NEActivationLayer act_layer_thread1(&ctx2);
+
+ const TensorShape tensor_shape(128, 128);
+ Tensor src_t0 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
+ Tensor dst_t0 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
+ Tensor src_t1 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
+ Tensor dst_t1 = create_tensor<Tensor>(tensor_shape, DataType::F32, 1);
+ ActivationLayerInfo activation_info(ActivationLayerInfo::ActivationFunction::LINEAR);
+
+ act_layer_thread0.configure(&src_t0, &dst_t0, activation_info);
+ act_layer_thread1.configure(&src_t1, &dst_t1, activation_info);
+
+ ARM_COMPUTE_EXPECT(src_t0.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst_t0.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(src_t1.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(dst_t1.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ // Allocate tensors
+ src_t0.allocator()->allocate();
+ dst_t0.allocator()->allocate();
+ src_t1.allocator()->allocate();
+ dst_t1.allocator()->allocate();
+
+ ARM_COMPUTE_EXPECT(!src_t0.info()->is_resizable(), framework::LogLevel::ERRORS);
+ ARM_COMPUTE_EXPECT(!src_t1.info()->is_resizable(), framework::LogLevel::ERRORS);
+
+ float min_bound = 0;
+ float max_bound = 0;
+ std::tie(min_bound, max_bound) = get_activation_layer_test_bounds<float>(ActivationLayerInfo::ActivationFunction::LINEAR, DataType::F32);
+ std::uniform_real_distribution<> distribution(min_bound, max_bound);
+ library->fill(Accessor(src_t0), distribution, 0);
+ library->fill(Accessor(src_t1), distribution, 0);
+
+ std::thread neon_thread1([&] { act_layer_thread0.run(); });
+ std::thread neon_thread2([&] { act_layer_thread1.run(); });
+
+ neon_thread1.join();
+ neon_thread2.join();
+
+ Window window;
+ window.use_tensor_dimensions(dst_t0.info()->tensor_shape());
+ Iterator t0_it(&dst_t0, window);
+ Iterator t1_it(&dst_t1, window);
+ execute_window_loop(window, [&](const Coordinates &)
+ {
+ const bool match = (*reinterpret_cast<float *>(t0_it.ptr()) == *reinterpret_cast<float *>(t1_it.ptr()));
+ ARM_COMPUTE_EXPECT(match, framework::LogLevel::ERRORS);
+ },
+ t0_it, t1_it);
+}
+#endif // !defined(BARE_METAL)
+
+TEST_SUITE_END() // RuntimeContext
+TEST_SUITE_END() // UNIT
+TEST_SUITE_END() // NEON
+} // namespace validation
+} // namespace test
+} // namespace arm_compute
diff --git a/tests/validation/fixtures/ActivationLayerFixture.h b/tests/validation/fixtures/ActivationLayerFixture.h
index d9f26b7368..8fa74979a8 100644
--- a/tests/validation/fixtures/ActivationLayerFixture.h
+++ b/tests/validation/fixtures/ActivationLayerFixture.h
@@ -29,6 +29,7 @@
#include "tests/AssetsLibrary.h"
#include "tests/Globals.h"
#include "tests/IAccessor.h"
+#include "tests/ParametersLibrary.h"
#include "tests/framework/Asserts.h"
#include "tests/framework/Fixture.h"
#include "tests/validation/Helpers.h"
@@ -94,7 +95,7 @@ protected:
TensorType dst = create_tensor<TensorType>(shape, _data_type, 1, _output_quantization_info);
// Create and configure function
- FunctionType act_layer;
+ FunctionType act_layer(parameters->get_ctx<TensorType>());
TensorType *dst_ptr = _in_place ? nullptr : &dst;