From db8485ac24135f17e9882c76196924435abc064f Mon Sep 17 00:00:00 2001 From: Pablo Tello Date: Tue, 24 Sep 2019 11:03:47 +0100 Subject: COMPMID-2205: CL runtime context. CL Interfaces implemented. Concrete classes implemented. One test (ActivationLayer) ported to the new interface. Change-Id: I283808bec36ccfc2f13fe048c45cbbee698ce525 Signed-off-by: Pablo Tello Reviewed-on: https://review.mlplatform.org/c/1998 Tested-by: Arm Jenkins Reviewed-by: Georgios Pinitas Comments-Addressed: Arm Jenkins --- arm_compute/core/CL/CLCoreRuntimeContext.h | 63 +++++++++++++ arm_compute/core/CL/CLHelpers.h | 13 +++ arm_compute/core/CL/CLKernelLibrary.h | 78 +++------------ arm_compute/core/CL/OpenCL.h | 3 +- .../core/CL/kernels/CLActivationLayerKernel.h | 11 ++- arm_compute/graph/backends/CL/CLDeviceBackend.h | 10 +- arm_compute/runtime/CL/CLBufferAllocator.h | 20 ++-- arm_compute/runtime/CL/CLHelpers.h | 10 ++ arm_compute/runtime/CL/CLMemoryRegion.h | 33 ++++--- arm_compute/runtime/CL/CLRuntimeContext.h | 70 ++++++++++++++ arm_compute/runtime/CL/CLScheduler.h | 74 ++++----------- arm_compute/runtime/CL/CLTensor.h | 27 +++++- arm_compute/runtime/CL/CLTensorAllocator.h | 6 +- arm_compute/runtime/CL/ICLSimpleFunction.h | 20 +++- .../runtime/CL/functions/CLActivationLayer.h | 2 +- arm_compute/runtime/GLES_COMPUTE/GCTensor.h | 9 +- arm_compute/runtime/Tensor.h | 10 +- src/core/CL/CLCoreRuntimeContext.cpp | 52 ++++++++++ src/core/CL/CLHelpers.cpp | 16 ++++ src/core/CL/CLKernelLibrary.cpp | 65 +++++++++++++ src/core/CL/OpenCL.cpp | 5 +- src/core/CL/kernels/CLActivationLayerKernel.cpp | 8 +- src/graph/backends/CL/CLDeviceBackend.cpp | 7 +- src/runtime/CL/CLBufferAllocator.cpp | 27 ++++-- src/runtime/CL/CLHelpers.cpp | 16 ++++ src/runtime/CL/CLMemoryRegion.cpp | 39 ++++---- src/runtime/CL/CLRuntimeContext.cpp | 67 +++++++++++++ src/runtime/CL/CLScheduler.cpp | 70 +++++++++++++- src/runtime/CL/CLTensor.cpp | 16 +++- src/runtime/CL/CLTensorAllocator.cpp | 54 ++++++++--- src/runtime/CL/ICLSimpleFunction.cpp | 13 +-- src/runtime/CL/functions/CLActivationLayer.cpp | 9 +- src/runtime/GLES_COMPUTE/GCTensor.cpp | 4 +- src/runtime/Tensor.cpp | 4 +- tests/Globals.h | 2 +- tests/ParametersLibrary.cpp | 41 -------- tests/ParametersLibrary.h | 76 --------------- tests/Utils.h | 10 +- tests/framework/Framework.cpp | 28 ++++-- tests/framework/ParametersLibrary.cpp | 54 +++++++++++ tests/framework/ParametersLibrary.h | 105 +++++++++++++++++++++ tests/main.cpp | 33 ++++--- tests/validation/CL/ActivationLayer.cpp | 9 +- tests/validation/fixtures/ActivationLayerFixture.h | 14 ++- utils/Utils.cpp | 1 + 45 files changed, 918 insertions(+), 386 deletions(-) create mode 100644 arm_compute/core/CL/CLCoreRuntimeContext.h create mode 100644 arm_compute/runtime/CL/CLRuntimeContext.h create mode 100644 src/core/CL/CLCoreRuntimeContext.cpp create mode 100644 src/runtime/CL/CLRuntimeContext.cpp delete mode 100644 tests/ParametersLibrary.cpp delete mode 100644 tests/ParametersLibrary.h create mode 100644 tests/framework/ParametersLibrary.cpp create mode 100644 tests/framework/ParametersLibrary.h diff --git a/arm_compute/core/CL/CLCoreRuntimeContext.h b/arm_compute/core/CL/CLCoreRuntimeContext.h new file mode 100644 index 0000000000..6e2bd43d53 --- /dev/null +++ b/arm_compute/core/CL/CLCoreRuntimeContext.h @@ -0,0 +1,63 @@ +/* + * 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_CLCORERUNTIME_CONTEXT_H__ +#define __ARM_COMPUTE_CLCORERUNTIME_CONTEXT_H__ + +#include "arm_compute/core/CL/OpenCL.h" + +namespace arm_compute +{ +class CLKernelLibrary; +/** Core runtime context */ +class CLCoreRuntimeContext final +{ +public: + /** Legacy constructor */ + CLCoreRuntimeContext(); + + /** Constructor */ + CLCoreRuntimeContext(CLKernelLibrary *kernel_lib, cl::Context ctx, cl::CommandQueue queue); + /** Destructor */ + ~CLCoreRuntimeContext() = default; + /** Default copy constructor */ + CLCoreRuntimeContext(const CLCoreRuntimeContext &) = default; + /** Default move constructor */ + CLCoreRuntimeContext(CLCoreRuntimeContext &&) = default; + /** Default copy assignment */ + CLCoreRuntimeContext &operator=(const CLCoreRuntimeContext &) = default; + /** Default move assignment operator */ + CLCoreRuntimeContext &operator=(CLCoreRuntimeContext &&) = default; + /** CPU Scheduler setter */ + + CLKernelLibrary *kernel_library() const; + cl::Context context(); + cl::CommandQueue queue(); + +private: + CLKernelLibrary *_kernel_lib{ nullptr }; + cl::Context _ctx{}; + cl::CommandQueue _queue{}; +}; +} // namespace arm_compute +#endif /*__ARM_COMPUTE_CLCORERUNTIME_CONTEXT_H__ */ diff --git a/arm_compute/core/CL/CLHelpers.h b/arm_compute/core/CL/CLHelpers.h index 16fe09fb96..1d647a86b0 100644 --- a/arm_compute/core/CL/CLHelpers.h +++ b/arm_compute/core/CL/CLHelpers.h @@ -34,6 +34,9 @@ namespace arm_compute { +class CLCoreRuntimeContext; +class CLBuildOptions; + enum class DataType; /** Max vector width of an OpenCL vector */ @@ -153,5 +156,15 @@ size_t preferred_vector_width(const cl::Device &device, DataType dt); * @return True if dummy work-items should be preferred to dispatch the NDRange */ bool preferred_dummy_work_items_support(const cl::Device &device); + +/** Creates an opencl kernel + * + * @param[in] ctx A context to be used to create the opencl kernel. + * @param[in] kernel_name The kernel name. + * @param[in] build_opts The build options to be used for the opencl kernel compilation. + * + * @return An opencl kernel + */ +cl::Kernel create_opencl_kernel(CLCoreRuntimeContext *ctx, const std::string &kernel_name, const CLBuildOptions &build_opts); } #endif /* __ARM_COMPUTE_CLHELPERS_H__ */ diff --git a/arm_compute/core/CL/CLKernelLibrary.h b/arm_compute/core/CL/CLKernelLibrary.h index 9f183f1232..f2282692f9 100644 --- a/arm_compute/core/CL/CLKernelLibrary.h +++ b/arm_compute/core/CL/CLKernelLibrary.h @@ -34,7 +34,7 @@ namespace arm_compute { /** Build options */ -class CLBuildOptions +class CLBuildOptions final { using StringSet = std::set; @@ -80,7 +80,7 @@ private: StringSet _build_opts; /**< Build options set */ }; /** Program class */ -class Program +class Program final { public: /** Default constructor. */ @@ -147,7 +147,7 @@ private: }; /** Kernel class */ -class Kernel +class Kernel final { public: /** Default Constructor. */ @@ -189,20 +189,19 @@ private: }; /** CLKernelLibrary class */ -class CLKernelLibrary +class CLKernelLibrary final { using StringSet = std::set; -private: +public: /** Default Constructor. */ CLKernelLibrary(); - -public: /** Prevent instances of this class from being copied */ CLKernelLibrary(const CLKernelLibrary &) = delete; /** Prevent instances of this class from being copied */ const CLKernelLibrary &operator=(const CLKernelLibrary &) = delete; /** Access the KernelLibrary singleton. + * This method has been deprecated and will be removed in the next release. * @return The KernelLibrary instance. */ static CLKernelLibrary &get(); @@ -212,26 +211,15 @@ public: * @param[in] context CL context used to create programs. * @param[in] device CL device for which the programs are created. */ - void init(std::string kernel_path, cl::Context context, cl::Device device) - { - _kernel_path = std::move(kernel_path); - _context = std::move(context); - _device = std::move(device); - } + void init(std::string kernel_path, cl::Context context, cl::Device device); /** Sets the path that the kernels reside in. * * @param[in] kernel_path Path of the kernel. */ - void set_kernel_path(const std::string &kernel_path) - { - _kernel_path = kernel_path; - }; + void set_kernel_path(const std::string &kernel_path); /** Gets the path that the kernels reside in. */ - std::string get_kernel_path() - { - return _kernel_path; - }; + std::string get_kernel_path(); /** Gets the source of the selected program. * * @param[in] program_name Program name. @@ -246,51 +234,22 @@ public: * * @param[in] context A CL context. */ - void set_context(cl::Context context) - { - _context = std::move(context); - if(_context.get() == nullptr) - { - _device = cl::Device(); - } - else - { - const auto cl_devices = _context.getInfo(); - - if(cl_devices.empty()) - { - _device = cl::Device(); - } - else - { - _device = cl_devices[0]; - } - } - } + void set_context(cl::Context context); /** Accessor for the associated CL context. * * @return A CL context. */ - cl::Context &context() - { - return _context; - } + cl::Context &context(); /** Gets the CL device for which the programs are created. */ - cl::Device &get_device() - { - return _device; - } + cl::Device &get_device(); /** Sets the CL device for which the programs are created. * * @param[in] device A CL device. */ - void set_device(cl::Device device) - { - _device = std::move(device); - } + void set_device(cl::Device device); /** Return the device version * @@ -321,17 +280,10 @@ public: /** Clear the library's cache of binary programs */ - void clear_programs_cache() - { - _programs_map.clear(); - _built_programs_map.clear(); - } + void clear_programs_cache(); /** Access the cache of built OpenCL programs */ - const std::map &get_built_programs() const - { - return _built_programs_map; - } + const std::map &get_built_programs() const; /** Add a new built program to the cache * diff --git a/arm_compute/core/CL/OpenCL.h b/arm_compute/core/CL/OpenCL.h index 912a53103a..b1d50e73b1 100644 --- a/arm_compute/core/CL/OpenCL.h +++ b/arm_compute/core/CL/OpenCL.h @@ -60,11 +60,10 @@ bool opencl_is_available(); /** Class for loading OpenCL symbols. */ class CLSymbols final { -private: +public: CLSymbols() = default; void load_symbols(void *handle); -public: /** Get the static instance of CLSymbols. * * @return The static instance of CLSymbols. diff --git a/arm_compute/core/CL/kernels/CLActivationLayerKernel.h b/arm_compute/core/CL/kernels/CLActivationLayerKernel.h index f20d6c3362..c64f7c42ac 100644 --- a/arm_compute/core/CL/kernels/CLActivationLayerKernel.h +++ b/arm_compute/core/CL/kernels/CLActivationLayerKernel.h @@ -29,13 +29,13 @@ namespace arm_compute { class ICLTensor; - +class CLCoreRuntimeContext; /** Interface for the activation layer kernel. */ class CLActivationLayerKernel : public ICLKernel { public: /** Default constructor */ - CLActivationLayerKernel(); + CLActivationLayerKernel(CLCoreRuntimeContext *ctx = nullptr); /** Prevent instances of this class from being copied (As this class contains pointers) */ CLActivationLayerKernel(const CLActivationLayerKernel &) = delete; /** Prevent instances of this class from being copied (As this class contains pointers) */ @@ -71,9 +71,10 @@ public: void run(const Window &window, cl::CommandQueue &queue) override; private: - ICLTensor *_input; - ICLTensor *_output; - bool _run_in_place; + ICLTensor *_input; + ICLTensor *_output; + bool _run_in_place; + CLCoreRuntimeContext *_ctx; }; } // namespace arm_compute #endif /*__ARM_COMPUTE_CLACTIVATIONLAYERKERNEL_H__ */ diff --git a/arm_compute/graph/backends/CL/CLDeviceBackend.h b/arm_compute/graph/backends/CL/CLDeviceBackend.h index 8569cf1f34..1239d5d3ad 100644 --- a/arm_compute/graph/backends/CL/CLDeviceBackend.h +++ b/arm_compute/graph/backends/CL/CLDeviceBackend.h @@ -31,6 +31,7 @@ namespace arm_compute { +class CLCoreRuntimeContext; namespace graph { namespace backends @@ -70,10 +71,11 @@ public: std::shared_ptr create_weights_manager() override; private: - int _context_count; /**< Counts how many contexts are currently using the backend */ - CLTuner _tuner; /**< CL kernel tuner */ - std::unique_ptr _allocator; /**< CL buffer affinity allocator */ - std::string _tuner_file; /**< Filename to load/store the tuner's values from */ + int _context_count; /**< Counts how many contexts are currently using the backend */ + CLTuner _tuner; /**< CL kernel tuner */ + std::unique_ptr _allocator; /**< CL buffer affinity allocator */ + std::string _tuner_file; /**< Filename to load/store the tuner's values from */ + std::unique_ptr _legacy_ctx; }; } // namespace backends } // namespace graph diff --git a/arm_compute/runtime/CL/CLBufferAllocator.h b/arm_compute/runtime/CL/CLBufferAllocator.h index 19a3e627ca..772402270b 100644 --- a/arm_compute/runtime/CL/CLBufferAllocator.h +++ b/arm_compute/runtime/CL/CLBufferAllocator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 ARM Limited. + * Copyright (c) 2017-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -26,19 +26,25 @@ #include "arm_compute/runtime/IAllocator.h" -#include "arm_compute/core/CL/OpenCL.h" -#include "arm_compute/runtime/CL/CLScheduler.h" - #include namespace arm_compute { +class CLCoreRuntimeContext; /** Default OpenCL cl buffer allocator implementation */ class CLBufferAllocator final : public IAllocator { public: - /** Default constructor */ - explicit CLBufferAllocator(cl::Context context = CLScheduler::get().context()); + /** Default constructor + * + * @param[in] ctx A runtime context. + */ + CLBufferAllocator(CLCoreRuntimeContext *ctx = nullptr); + + /** Default copy constructor */ + CLBufferAllocator(const CLBufferAllocator &) = default; + /** Default copy assignment operator */ + CLBufferAllocator &operator=(const CLBufferAllocator &) = default; // Inherited methods overridden: void *allocate(size_t size, size_t alignment) override; @@ -46,7 +52,7 @@ public: std::unique_ptr make_region(size_t size, size_t alignment) override; private: - cl::Context _context; + CLCoreRuntimeContext *_ctx; }; } // arm_compute #endif /*__ARM_COMPUTE_CLBUFFERALLOCATOR_H__ */ diff --git a/arm_compute/runtime/CL/CLHelpers.h b/arm_compute/runtime/CL/CLHelpers.h index f3b11f8b75..84f155afd2 100644 --- a/arm_compute/runtime/CL/CLHelpers.h +++ b/arm_compute/runtime/CL/CLHelpers.h @@ -25,9 +25,12 @@ #define __ARM_COMPUTE_CL_HELPERS_H__ #include "arm_compute/core/CL/OpenCL.h" +#include "arm_compute/runtime/IScheduler.h" namespace arm_compute { +class CLRuntimeContext; +class ICLKernel; /** This function creates an OpenCL context and a device. * * @note In debug builds, the function will automatically enable cl_arm_printf if the driver/device supports it. @@ -37,5 +40,12 @@ namespace arm_compute * a value telling why the function failed. */ std::tuple create_opencl_context_and_device(); +/** 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] flush (Optional) Specifies if the command queue will be flushed after running the kernel. + */ +void schedule_kernel_on_ctx(CLRuntimeContext *ctx, ICLKernel *kernel, bool flush = true); } // namespace arm_compute #endif /* __ARM_COMPUTE_CL_HELPERS_H__ */ diff --git a/arm_compute/runtime/CL/CLMemoryRegion.h b/arm_compute/runtime/CL/CLMemoryRegion.h index dbfd8225ca..6f7c3cd9a8 100644 --- a/arm_compute/runtime/CL/CLMemoryRegion.h +++ b/arm_compute/runtime/CL/CLMemoryRegion.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018 ARM Limited. + * Copyright (c) 2018-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -31,16 +31,17 @@ namespace arm_compute { +class CLCoreRuntimeContext; /** OpenCL memory region interface */ class ICLMemoryRegion : public IMemoryRegion { public: /** Constructor * - * @param[in] ctx OpenCL context + * @param[in] ctx Runtime context * @param[in] size Region size */ - ICLMemoryRegion(cl::Context ctx, size_t size); + ICLMemoryRegion(CLCoreRuntimeContext *ctx, size_t size); /** Default Destructor */ virtual ~ICLMemoryRegion() = default; /** Prevent instances of this class from being copied (As this class contains pointers) */ @@ -86,9 +87,10 @@ public: std::unique_ptr extract_subregion(size_t offset, size_t size) override; protected: - cl::Context _ctx; - void *_mapping; - cl::Buffer _mem; + cl::CommandQueue _queue; + cl::Context _ctx; + void *_mapping; + cl::Buffer _mem; }; /** OpenCL buffer memory region implementation */ @@ -97,16 +99,17 @@ class CLBufferMemoryRegion final : public ICLMemoryRegion public: /** Constructor * - * @param[in] ctx OpenCL context + * @param[in] ctx Runtime context * @param[in] flags Memory flags * @param[in] size Region size */ - CLBufferMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size); + CLBufferMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size); /** Constructor * * @param[in] buffer Buffer to be used as a memory region + * @param[in] ctx Runtime context */ - CLBufferMemoryRegion(const cl::Buffer &buffer); + CLBufferMemoryRegion(const cl::Buffer &buffer, CLCoreRuntimeContext *ctx); // Inherited methods overridden : void *ptr() final; @@ -120,12 +123,12 @@ class ICLSVMMemoryRegion : public ICLMemoryRegion protected: /** Constructor * - * @param[in] ctx OpenCL context + * @param[in] ctx Runtime context * @param[in] flags Memory flags * @param[in] size Region size * @param[in] alignment Alignment */ - ICLSVMMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size, size_t alignment); + ICLSVMMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size, size_t alignment); /** Destructor */ virtual ~ICLSVMMemoryRegion(); /** Prevent instances of this class from being copied (As this class contains pointers) */ @@ -150,12 +153,12 @@ class CLCoarseSVMMemoryRegion final : public ICLSVMMemoryRegion public: /** Constructor * - * @param[in] ctx OpenCL context + * @param[in] ctx Runtime context * @param[in] flags Memory flags * @param[in] size Region size * @param[in] alignment Alignment */ - CLCoarseSVMMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size, size_t alignment); + CLCoarseSVMMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size, size_t alignment); // Inherited methods overridden : void *map(cl::CommandQueue &q, bool blocking) final; @@ -168,12 +171,12 @@ class CLFineSVMMemoryRegion final : public ICLSVMMemoryRegion public: /** Constructor * - * @param[in] ctx OpenCL context + * @param[in] ctx Runtime context * @param[in] flags Memory flags * @param[in] size Region size * @param[in] alignment Alignment */ - CLFineSVMMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size, size_t alignment); + CLFineSVMMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size, size_t alignment); // Inherited methods overridden : void *map(cl::CommandQueue &q, bool blocking) final; diff --git a/arm_compute/runtime/CL/CLRuntimeContext.h b/arm_compute/runtime/CL/CLRuntimeContext.h new file mode 100644 index 0000000000..971dfd2224 --- /dev/null +++ b/arm_compute/runtime/CL/CLRuntimeContext.h @@ -0,0 +1,70 @@ +/* + * 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_CLRUNTIME_CONTEXT_H__ +#define __ARM_COMPUTE_CLRUNTIME_CONTEXT_H__ + +#include "arm_compute/core/CL/CLCoreRuntimeContext.h" +#include "arm_compute/core/CL/CLKernelLibrary.h" +#include "arm_compute/core/CL/OpenCL.h" +#include "arm_compute/runtime/CL/CLScheduler.h" +#include "arm_compute/runtime/CL/CLTuner.h" +#include "arm_compute/runtime/IScheduler.h" +#include "arm_compute/runtime/RuntimeContext.h" + +namespace arm_compute +{ +/** Runtime context */ +class CLRuntimeContext : public RuntimeContext +{ +public: + /** Default Constructor */ + CLRuntimeContext(); + /** Destructor */ + ~CLRuntimeContext() = default; + /** Prevent instances of this class from being copied (As this class contains pointers) */ + CLRuntimeContext(const CLRuntimeContext &) = delete; + /** Default move constructor */ + CLRuntimeContext(CLRuntimeContext &&) = default; + /** Prevent instances of this class from being copied (As this class contains pointers) */ + CLRuntimeContext &operator=(const CLRuntimeContext &) = delete; + /** Default move assignment operator */ + CLRuntimeContext &operator=(CLRuntimeContext &&) = default; + /** CPU Scheduler setter */ + void set_gpu_scheduler(CLScheduler *scheduler); + + // Inherited overridden methods + CLScheduler *gpu_scheduler(); + CLKernelLibrary &kernel_library(); + CLCoreRuntimeContext *core_runtime_context(); + +private: + std::unique_ptr _gpu_owned_scheduler{ nullptr }; + CLScheduler *_gpu_scheduler{ nullptr }; + CLTuner _tuner{ false }; + CLKernelLibrary _kernel_lib{}; + CLSymbols _symbols{}; + CLCoreRuntimeContext _core_context{}; +}; +} // namespace arm_compute +#endif /*__ARM_COMPUTE_CLRUNTIME_CONTEXT_H__ */ diff --git a/arm_compute/runtime/CL/CLScheduler.h b/arm_compute/runtime/CL/CLScheduler.h index 53cb88ad5b..720c8b37f5 100644 --- a/arm_compute/runtime/CL/CLScheduler.h +++ b/arm_compute/runtime/CL/CLScheduler.h @@ -25,7 +25,6 @@ #define __ARM_COMPUTE_CLSCHEDULER_H__ #include "arm_compute/core/CL/CLHelpers.h" -#include "arm_compute/core/CL/CLKernelLibrary.h" #include "arm_compute/core/CL/CLTypes.h" #include "arm_compute/core/CL/OpenCL.h" #include "arm_compute/core/Error.h" @@ -35,21 +34,21 @@ namespace arm_compute { class ICLKernel; - +class ICLTuner; /** Provides global access to a CL context and command queue. */ -class CLScheduler +class CLScheduler final { -private: +public: /** Constructor */ CLScheduler(); /** Prevent instances of this class from being copied (As this class contains pointers) */ CLScheduler(const CLScheduler &) = delete; /** Prevent instances of this class from being copied (As this class contains pointers) */ CLScheduler &operator=(const CLScheduler &) = delete; - -public: + /** Default destructor */ + ~CLScheduler() = default; /** Access the scheduler singleton. - * + * This method has been deprecated and will be removed in future releases * @return The scheduler */ static CLScheduler &get(); @@ -88,31 +87,19 @@ public: * * @return A CL context. */ - cl::Context &context() - { - ARM_COMPUTE_ERROR_ON(!_is_initialised); - _context = CLKernelLibrary::get().context(); - return _context; - } + cl::Context &context(); /** Accessor for the associated CL command queue. * * @return A CL command queue. */ - cl::CommandQueue &queue() - { - ARM_COMPUTE_ERROR_ON(!_is_initialised); - return _queue; - } + cl::CommandQueue &queue(); /** Get the target GPU. * * @return The target GPU. */ - GPUTarget target() const - { - return _target; - } + GPUTarget target() const; /** Accessor to set the CL context to be used by the scheduler. * @@ -124,63 +111,36 @@ public: * * @param[in] queue A CL command queue. */ - void set_queue(cl::CommandQueue queue) - { - _queue = std::move(queue); - } + void set_queue(cl::CommandQueue queue); /** Accessor to set target GPU to be used by the scheduler. * * @param[in] target The target GPU. */ - void set_target(GPUTarget target) - { - _target = target; - } + void set_target(GPUTarget target); /** Accessor to set the CL tuner to be used by the scheduler. * * @param[in] tuner A CL tuner */ - void set_tuner(ICLTuner *tuner) - { - _cl_tuner = tuner; - } + void set_tuner(ICLTuner *tuner); /** Blocks until all commands in the associated command queue have finished. */ - void sync() - { - _queue.finish(); - } + void sync(); /** Enqueues a marker into the associated command queue and return the event. * * @return An event that can be waited on to block the executing thread. */ - cl::Event enqueue_sync_event() - { - cl::Event event; - _queue.enqueueMarker(&event); - - return event; - } + cl::Event enqueue_sync_event(); /** Tunes OpenCL kernel * * @param[in] kernel Kernel to tune */ - void tune_kernel_static(ICLKernel &kernel) - { - if(_cl_tuner != nullptr) - { - _cl_tuner->tune_kernel_static(kernel); - } - } - - bool is_initialised() const - { - return _is_initialised; - } + void tune_kernel_static(ICLKernel &kernel); + + bool is_initialised() const; private: /** Flag to ensure symbols initialisation is happening before Scheduler creation */ diff --git a/arm_compute/runtime/CL/CLTensor.h b/arm_compute/runtime/CL/CLTensor.h index bc72839492..c108d1afad 100644 --- a/arm_compute/runtime/CL/CLTensor.h +++ b/arm_compute/runtime/CL/CLTensor.h @@ -35,13 +35,32 @@ namespace arm_compute // Forward declarations class ITensorAllocator; class ITensorInfo; - +class IRuntimeContext; +class CLRuntimeContext; /** Basic implementation of the OpenCL tensor interface */ class CLTensor : public ICLTensor, public IMemoryManageable { public: - /** Constructor */ - CLTensor(); + /** Constructor. + * + * @param[in] ctx (Optional) Pointer to a @ref CLRuntimeContext. + * If nullptr is passed in, the legacy api using the singletons will be used. Otherwise the memory for the + * tensor will allocate on the context passed in. + * The singletons legacy api has been deprecated and will be removed. + */ + CLTensor(IRuntimeContext *ctx = nullptr); + + /** Destructor */ + ~CLTensor() = default; + /** Default copy constructor */ + CLTensor(const CLTensor &) = default; + /** Default move constructor */ + CLTensor(CLTensor &&) = default; + /** Default copy assignment */ + CLTensor &operator=(const CLTensor &) = default; + /** Default move assignment operator */ + CLTensor &operator=(CLTensor &&) = default; + /** Return a pointer to the tensor's allocator * * @return A pointer to the tensor's allocator @@ -69,6 +88,7 @@ public: const cl::Buffer &cl_buffer() const override; CLQuantization quantization() const override; void associate_memory_group(IMemoryGroup *memory_group) override; + CLRuntimeContext *context(); protected: // Inherited methods overridden: @@ -77,6 +97,7 @@ protected: private: mutable CLTensorAllocator _allocator; /**< Instance of the OpenCL tensor allocator */ + CLRuntimeContext *_ctx{ nullptr }; }; /** OpenCL Image */ diff --git a/arm_compute/runtime/CL/CLTensorAllocator.h b/arm_compute/runtime/CL/CLTensorAllocator.h index 3450c72d61..b3ffd8b949 100644 --- a/arm_compute/runtime/CL/CLTensorAllocator.h +++ b/arm_compute/runtime/CL/CLTensorAllocator.h @@ -37,7 +37,7 @@ namespace arm_compute { class CLTensor; - +class CLRuntimeContext; /** Basic implementation of a CL memory tensor allocator. */ class CLTensorAllocator : public ITensorAllocator { @@ -45,8 +45,9 @@ public: /** Default constructor. * * @param[in] owner (Optional) Owner of the allocator. + * @param[in] ctx (Optional) Runtime context. */ - CLTensorAllocator(IMemoryManageable *owner = nullptr); + CLTensorAllocator(IMemoryManageable *owner = nullptr, CLRuntimeContext *ctx = nullptr); /** Prevent instances of this class from being copied (As this class contains pointers) */ CLTensorAllocator(const CLTensorAllocator &) = delete; /** Prevent instances of this class from being copy assigned (As this class contains pointers) */ @@ -139,6 +140,7 @@ private: static const cl::Buffer _empty_buffer; private: + CLRuntimeContext *_ctx; IMemoryManageable *_owner; /**< Memory manageable object that owns the allocator */ IMemoryGroup *_associated_memory_group; /**< Registered memory manager */ CLMemory _memory; /**< OpenCL memory */ diff --git a/arm_compute/runtime/CL/ICLSimpleFunction.h b/arm_compute/runtime/CL/ICLSimpleFunction.h index 130c58a98c..8399a3d58e 100644 --- a/arm_compute/runtime/CL/ICLSimpleFunction.h +++ b/arm_compute/runtime/CL/ICLSimpleFunction.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017 ARM Limited. + * Copyright (c) 2016-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -32,12 +32,25 @@ namespace arm_compute { +class CLRuntimeContext; /** Basic interface for functions which have a single OpenCL kernel */ class ICLSimpleFunction : public IFunction { public: - /** Default constructor */ - ICLSimpleFunction(); + /** Constructor + * + * @param[in] ctx Runtime context to be used by the function + */ + ICLSimpleFunction(CLRuntimeContext *ctx = nullptr); + + /** Prevent instances of this class from being copied (As this class contains pointers) */ + ICLSimpleFunction(const ICLSimpleFunction &) = delete; + /** Default move constructor */ + ICLSimpleFunction(ICLSimpleFunction &&) = default; + /** Prevent instances of this class from being copied (As this class contains pointers) */ + ICLSimpleFunction &operator=(const ICLSimpleFunction &) = delete; + /** Default move assignment operator */ + ICLSimpleFunction &operator=(ICLSimpleFunction &&) = default; // Inherited methods overridden: void run() override final; @@ -45,6 +58,7 @@ public: protected: std::unique_ptr _kernel; /**< Kernel to run */ CLFillBorderKernel _border_handler; /**< Kernel to handle borders */ + CLRuntimeContext *_ctx; /**< Context to use */ }; } #endif /*__ARM_COMPUTE_ICLSIMPLEFUNCTION_H__ */ diff --git a/arm_compute/runtime/CL/functions/CLActivationLayer.h b/arm_compute/runtime/CL/functions/CLActivationLayer.h index 1201d7d355..e1e3e877d5 100644 --- a/arm_compute/runtime/CL/functions/CLActivationLayer.h +++ b/arm_compute/runtime/CL/functions/CLActivationLayer.h @@ -43,7 +43,7 @@ public: * * @param[in] ctx Runtime context to be used by the function */ - CLActivationLayer(void *ctx = nullptr); + CLActivationLayer(CLRuntimeContext *ctx = nullptr); /** Prevent instances of this class from being copied (As this class contains pointers) */ CLActivationLayer(const CLActivationLayer &) = delete; /** Default move constructor */ diff --git a/arm_compute/runtime/GLES_COMPUTE/GCTensor.h b/arm_compute/runtime/GLES_COMPUTE/GCTensor.h index 344c78852b..a308ba0237 100644 --- a/arm_compute/runtime/GLES_COMPUTE/GCTensor.h +++ b/arm_compute/runtime/GLES_COMPUTE/GCTensor.h @@ -32,13 +32,18 @@ namespace arm_compute { class ITensorAllocator; class ITensorInfo; +class IRuntimeContext; /** Interface for OpenGL ES tensor */ class GCTensor : public IGCTensor, public IMemoryManageable { public: - /** Default constructor */ - GCTensor(); + /** Default constructor + * + * @param[in] ctx (Optional) Pointer to the runtime context. + * + */ + GCTensor(IRuntimeContext *ctx = nullptr); /** Prevent instances of this class from being copied (As this class contains pointers) */ GCTensor(const GCTensor &) = delete; diff --git a/arm_compute/runtime/Tensor.h b/arm_compute/runtime/Tensor.h index 6fa7c8ca0e..e469f70817 100644 --- a/arm_compute/runtime/Tensor.h +++ b/arm_compute/runtime/Tensor.h @@ -32,13 +32,17 @@ namespace arm_compute { class ITensorInfo; - +class IRuntimeContext; /** Basic implementation of the tensor interface */ class Tensor : public ITensor, public IMemoryManageable { public: - /** Constructor */ - Tensor(); + /** Constructor + * + * @param[in] ctx (Optional) Pointer to the runtime context. + * + */ + Tensor(IRuntimeContext *ctx = nullptr); /** Destructor: free the tensor's memory */ ~Tensor() = default; /** Allow instances of this class to be move constructed */ diff --git a/src/core/CL/CLCoreRuntimeContext.cpp b/src/core/CL/CLCoreRuntimeContext.cpp new file mode 100644 index 0000000000..f9efad2c0d --- /dev/null +++ b/src/core/CL/CLCoreRuntimeContext.cpp @@ -0,0 +1,52 @@ +/* + * 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/core/CL/CLCoreRuntimeContext.h" + +namespace arm_compute +{ +cl::Context CLCoreRuntimeContext::context() +{ + return _ctx; +} + +cl::CommandQueue CLCoreRuntimeContext::queue() +{ + return _queue; +} + +CLCoreRuntimeContext::CLCoreRuntimeContext() + : _kernel_lib(nullptr), _ctx(), _queue() +{ +} + +CLCoreRuntimeContext::CLCoreRuntimeContext(CLKernelLibrary *kernel_lib, cl::Context ctx, cl::CommandQueue queue) + : _kernel_lib(kernel_lib), _ctx(ctx), _queue(queue) +{ +} + +CLKernelLibrary *CLCoreRuntimeContext::kernel_library() const +{ + return _kernel_lib; +} +} // namespace arm_compute diff --git a/src/core/CL/CLHelpers.cpp b/src/core/CL/CLHelpers.cpp index d051810090..a3c73677c7 100644 --- a/src/core/CL/CLHelpers.cpp +++ b/src/core/CL/CLHelpers.cpp @@ -22,6 +22,8 @@ * SOFTWARE. */ #include "arm_compute/core/CL/CLHelpers.h" +#include "arm_compute/core/CL/CLCoreRuntimeContext.h" +#include "arm_compute/core/CL/CLKernelLibrary.h" #include "arm_compute/core/CL/CLTypes.h" #include "arm_compute/core/Error.h" #include "arm_compute/core/Log.h" @@ -283,4 +285,18 @@ bool preferred_dummy_work_items_support(const cl::Device &device) // TODO (COMPMID-2044) return true; } + +cl::Kernel create_opencl_kernel(CLCoreRuntimeContext *ctx, const std::string &kernel_name, const CLBuildOptions &build_opts) +{ + if(ctx && ctx->kernel_library()) + { + //New api going through the core context + return static_cast(ctx->kernel_library()->create_kernel(kernel_name, build_opts.options())); + } + else + { + //Legacy code through the singleton + return static_cast(CLKernelLibrary::get().create_kernel(kernel_name, build_opts.options())); + } +} } // namespace arm_compute diff --git a/src/core/CL/CLKernelLibrary.cpp b/src/core/CL/CLKernelLibrary.cpp index 7b7263fca7..c27f886129 100644 --- a/src/core/CL/CLKernelLibrary.cpp +++ b/src/core/CL/CLKernelLibrary.cpp @@ -1144,6 +1144,49 @@ Kernel CLKernelLibrary::create_kernel(const std::string &kernel_name, const Stri return Kernel(kernel_name, cl_program); } +void CLKernelLibrary::init(std::string kernel_path, cl::Context context, cl::Device device) +{ + _kernel_path = std::move(kernel_path); + _context = std::move(context); + _device = std::move(device); +} + +void CLKernelLibrary::set_kernel_path(const std::string &kernel_path) +{ + _kernel_path = kernel_path; +} + +cl::Context &CLKernelLibrary::context() +{ + return _context; +} + +cl::Device &CLKernelLibrary::get_device() +{ + return _device; +} + +void CLKernelLibrary::set_device(cl::Device device) +{ + _device = std::move(device); +} + +std::string CLKernelLibrary::get_kernel_path() +{ + return _kernel_path; +} + +void CLKernelLibrary::clear_programs_cache() +{ + _programs_map.clear(); + _built_programs_map.clear(); +} + +const std::map &CLKernelLibrary::get_built_programs() const +{ + return _built_programs_map; +} + void CLKernelLibrary::add_built_program(const std::string &built_program_name, const cl::Program &program) { _built_programs_map.emplace(built_program_name, program); @@ -1205,6 +1248,28 @@ const Program &CLKernelLibrary::load_program(const std::string &program_name) co return new_program.first->second; } +void CLKernelLibrary::set_context(cl::Context context) +{ + _context = std::move(context); + if(_context.get() == nullptr) + { + _device = cl::Device(); + } + else + { + const auto cl_devices = _context.getInfo(); + + if(cl_devices.empty()) + { + _device = cl::Device(); + } + else + { + _device = cl_devices[0]; + } + } +} + std::string CLKernelLibrary::stringify_set(const StringSet &s) const { std::string concat_set; diff --git a/src/core/CL/OpenCL.cpp b/src/core/CL/OpenCL.cpp index 1ce1b526d7..74c5b041d7 100644 --- a/src/core/CL/OpenCL.cpp +++ b/src/core/CL/OpenCL.cpp @@ -27,6 +27,8 @@ #include "arm_compute/core/CL/OpenCL.h" #pragma GCC diagnostic pop +#include "arm_compute/core/Error.h" + #include #include @@ -54,6 +56,7 @@ bool CLSymbols::load_default() { if(load(lib)) { + ARM_COMPUTE_ERROR_ON_MSG(this->clBuildProgram_ptr == nullptr, "Failed to load OpenCL symbols from shared library"); return true; } } @@ -948,4 +951,4 @@ clImportMemoryARM(cl_context context, } return nullptr; } -} \ No newline at end of file +} diff --git a/src/core/CL/kernels/CLActivationLayerKernel.cpp b/src/core/CL/kernels/CLActivationLayerKernel.cpp index 97a0ff6c6c..5062fd1801 100644 --- a/src/core/CL/kernels/CLActivationLayerKernel.cpp +++ b/src/core/CL/kernels/CLActivationLayerKernel.cpp @@ -23,8 +23,8 @@ */ #include "arm_compute/core/CL/kernels/CLActivationLayerKernel.h" +#include "arm_compute/core/CL/CLCoreRuntimeContext.h" #include "arm_compute/core/CL/CLHelpers.h" -#include "arm_compute/core/CL/CLKernelLibrary.h" #include "arm_compute/core/CL/CLValidate.h" #include "arm_compute/core/CL/ICLTensor.h" #include "arm_compute/core/Helpers.h" @@ -111,8 +111,8 @@ std::pair validate_and_configure_window(ITensorInfo *input, ITen } } // namespace -CLActivationLayerKernel::CLActivationLayerKernel() - : _input(nullptr), _output(nullptr), _run_in_place(false) +CLActivationLayerKernel::CLActivationLayerKernel(CLCoreRuntimeContext *ctx) + : _input(nullptr), _output(nullptr), _run_in_place(false), _ctx(ctx) { } @@ -205,8 +205,8 @@ void CLActivationLayerKernel::configure(ICLTensor *input, ICLTensor *output, Act { kernel_name += perform_activation_in_float ? std::string("_quant_f32") : std::string("_quant"); } - _kernel = static_cast(CLKernelLibrary::get().create_kernel(kernel_name, build_opts.options())); + _kernel = create_opencl_kernel(_ctx, kernel_name, build_opts); // Make sure _kernel is initialized before calling the parent's configure _input = input; _output = output; diff --git a/src/graph/backends/CL/CLDeviceBackend.cpp b/src/graph/backends/CL/CLDeviceBackend.cpp index ea3b6b801a..58c666c3cc 100644 --- a/src/graph/backends/CL/CLDeviceBackend.cpp +++ b/src/graph/backends/CL/CLDeviceBackend.cpp @@ -34,6 +34,7 @@ #include "arm_compute/graph/backends/CL/CLSubTensorHandle.h" #include "arm_compute/graph/backends/CL/CLTensorHandle.h" +#include "arm_compute/core/CL/CLCoreRuntimeContext.h" #include "arm_compute/core/TensorInfo.h" #include "arm_compute/runtime/BlobLifetimeManager.h" #include "arm_compute/runtime/CL/CLBufferAllocator.h" @@ -64,7 +65,7 @@ bool file_exists(const std::string &filename) static detail::BackendRegistrar CLDeviceBackend_registrar(Target::CL); CLDeviceBackend::CLDeviceBackend() - : _context_count(0), _tuner(), _allocator(nullptr), _tuner_file() + : _context_count(0), _tuner(), _allocator(nullptr), _tuner_file(), _legacy_ctx() { } @@ -91,9 +92,9 @@ void CLDeviceBackend::initialize_backend() { // Setup Scheduler CLScheduler::get().default_init(&_tuner); - + _legacy_ctx = support::cpp14::make_unique(nullptr, CLScheduler::get().context(), CLScheduler::get().queue()); // Create allocator with new context - _allocator = support::cpp14::make_unique(); + _allocator = support::cpp14::make_unique(_legacy_ctx.get()); } void CLDeviceBackend::release_backend_context(GraphContext &ctx) diff --git a/src/runtime/CL/CLBufferAllocator.cpp b/src/runtime/CL/CLBufferAllocator.cpp index 84789e70d2..ed27320650 100644 --- a/src/runtime/CL/CLBufferAllocator.cpp +++ b/src/runtime/CL/CLBufferAllocator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 ARM Limited. + * Copyright (c) 2017-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -22,25 +22,35 @@ * SOFTWARE. */ #include "arm_compute/runtime/CL/CLBufferAllocator.h" -#include "arm_compute/runtime/CL/CLMemoryRegion.h" +#include "arm_compute/core/CL/CLCoreRuntimeContext.h" #include "arm_compute/core/CL/OpenCL.h" #include "arm_compute/core/Error.h" +#include "arm_compute/runtime/CL/CLMemoryRegion.h" +#include "arm_compute/runtime/CL/CLScheduler.h" #include "support/ToolchainSupport.h" #include -using namespace arm_compute; - -CLBufferAllocator::CLBufferAllocator(cl::Context context) - : _context(std::move(context)) +namespace arm_compute +{ +CLBufferAllocator::CLBufferAllocator(CLCoreRuntimeContext *ctx) + : _ctx(ctx) { } void *CLBufferAllocator::allocate(size_t size, size_t alignment) { ARM_COMPUTE_UNUSED(alignment); - cl_mem buf = clCreateBuffer(_context.get(), CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size, nullptr, nullptr); + cl_mem buf; + if(_ctx == nullptr) + { + buf = clCreateBuffer(CLScheduler::get().context().get(), CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size, nullptr, nullptr); + } + else + { + buf = clCreateBuffer(_ctx->context().get(), CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size, nullptr, nullptr); + } return static_cast(buf); } @@ -53,5 +63,6 @@ void CLBufferAllocator::free(void *ptr) std::unique_ptr CLBufferAllocator::make_region(size_t size, size_t alignment) { ARM_COMPUTE_UNUSED(alignment); - return arm_compute::support::cpp14::make_unique(_context, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size); + return arm_compute::support::cpp14::make_unique(_ctx, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size); } +} // namespace arm_compute diff --git a/src/runtime/CL/CLHelpers.cpp b/src/runtime/CL/CLHelpers.cpp index edfc8ed2aa..c4c7ee2107 100644 --- a/src/runtime/CL/CLHelpers.cpp +++ b/src/runtime/CL/CLHelpers.cpp @@ -26,6 +26,7 @@ #include "arm_compute/core/CL/CLHelpers.h" #include "arm_compute/core/Error.h" +#include "arm_compute/runtime/CL/CLRuntimeContext.h" namespace { @@ -103,4 +104,19 @@ create_opencl_context_and_device() ARM_COMPUTE_ERROR_ON_MSG(err != CL_SUCCESS, "Failed to create OpenCL context"); return std::make_tuple(cl_context, device, err); } + +void schedule_kernel_on_ctx(CLRuntimeContext *ctx, ICLKernel *kernel, bool flush) +{ + ARM_COMPUTE_ERROR_ON_NULLPTR(kernel); + if(ctx) + { + ARM_COMPUTE_ERROR_ON(ctx->gpu_scheduler() == nullptr); + ctx->gpu_scheduler()->enqueue(*kernel, flush); + } + else + { + CLScheduler::get().enqueue(*kernel, flush); + } +} + } // namespace arm_compute diff --git a/src/runtime/CL/CLMemoryRegion.cpp b/src/runtime/CL/CLMemoryRegion.cpp index 2976903c93..52906a893f 100644 --- a/src/runtime/CL/CLMemoryRegion.cpp +++ b/src/runtime/CL/CLMemoryRegion.cpp @@ -23,13 +23,18 @@ */ #include "arm_compute/runtime/CL/CLMemoryRegion.h" +#include "arm_compute/core/CL/CLCoreRuntimeContext.h" #include "arm_compute/core/Error.h" #include "arm_compute/runtime/CL/CLScheduler.h" namespace arm_compute { -ICLMemoryRegion::ICLMemoryRegion(cl::Context ctx, size_t size) - : IMemoryRegion(size), _ctx(std::move(ctx)), _mapping(nullptr), _mem() +ICLMemoryRegion::ICLMemoryRegion(CLCoreRuntimeContext *ctx, size_t size) + : IMemoryRegion(size), + _queue((ctx != nullptr) ? ctx->queue() : CLScheduler::get().queue()), + _ctx((ctx != nullptr) ? ctx->context() : CLScheduler::get().context()), + _mapping(nullptr), + _mem() { } @@ -54,17 +59,17 @@ std::unique_ptr ICLMemoryRegion::extract_subregion(size_t offset, return nullptr; } -CLBufferMemoryRegion::CLBufferMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size) - : ICLMemoryRegion(std::move(ctx), size) +CLBufferMemoryRegion::CLBufferMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size) + : ICLMemoryRegion(ctx, size) { if(_size != 0) { - _mem = cl::Buffer(_ctx, flags, _size); + _mem = cl::Buffer((ctx != nullptr) ? ctx->context() : CLScheduler::get().context(), flags, _size); } } -CLBufferMemoryRegion::CLBufferMemoryRegion(const cl::Buffer &buffer) - : ICLMemoryRegion(buffer.getInfo(), buffer.getInfo()) +CLBufferMemoryRegion::CLBufferMemoryRegion(const cl::Buffer &buffer, CLCoreRuntimeContext *ctx) + : ICLMemoryRegion(ctx, buffer.getInfo()) { _mem = buffer; } @@ -88,15 +93,15 @@ void CLBufferMemoryRegion::unmap(cl::CommandQueue &q) _mapping = nullptr; } -ICLSVMMemoryRegion::ICLSVMMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size, size_t alignment) - : ICLMemoryRegion(std::move(ctx), size), _ptr(nullptr) +ICLSVMMemoryRegion::ICLSVMMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size, size_t alignment) + : ICLMemoryRegion(ctx, size), _ptr(nullptr) { if(size != 0) { - _ptr = clSVMAlloc(_ctx.get(), flags, size, alignment); + _ptr = clSVMAlloc((ctx != nullptr) ? ctx->context().get() : CLScheduler::get().context().get(), flags, size, alignment); if(_ptr != nullptr) { - _mem = cl::Buffer(_ctx, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, _size, _ptr); + _mem = cl::Buffer((ctx != nullptr) ? ctx->context() : CLScheduler::get().context(), CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, _size, _ptr); } } } @@ -107,7 +112,7 @@ ICLSVMMemoryRegion::~ICLSVMMemoryRegion() { try { - clFinish(CLScheduler::get().queue().get()); + clFinish(_queue.get()); _mem = cl::Buffer(); clSVMFree(_ctx.get(), _ptr); } @@ -122,8 +127,8 @@ void *ICLSVMMemoryRegion::ptr() return _ptr; } -CLCoarseSVMMemoryRegion::CLCoarseSVMMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size, size_t alignment) - : ICLSVMMemoryRegion(std::move(ctx), flags, size, alignment) +CLCoarseSVMMemoryRegion::CLCoarseSVMMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size, size_t alignment) + : ICLSVMMemoryRegion(ctx, flags, size, alignment) { } @@ -142,8 +147,8 @@ void CLCoarseSVMMemoryRegion::unmap(cl::CommandQueue &q) _mapping = nullptr; } -CLFineSVMMemoryRegion::CLFineSVMMemoryRegion(cl::Context ctx, cl_mem_flags flags, size_t size, size_t alignment) - : ICLSVMMemoryRegion(std::move(ctx), flags, size, alignment) +CLFineSVMMemoryRegion::CLFineSVMMemoryRegion(CLCoreRuntimeContext *ctx, cl_mem_flags flags, size_t size, size_t alignment) + : ICLSVMMemoryRegion(ctx, flags, size, alignment) { } @@ -162,4 +167,4 @@ void CLFineSVMMemoryRegion::unmap(cl::CommandQueue &q) ARM_COMPUTE_UNUSED(q); _mapping = nullptr; } -} // namespace arm_compute \ No newline at end of file +} // namespace arm_compute diff --git a/src/runtime/CL/CLRuntimeContext.cpp b/src/runtime/CL/CLRuntimeContext.cpp new file mode 100644 index 0000000000..49e4c10c84 --- /dev/null +++ b/src/runtime/CL/CLRuntimeContext.cpp @@ -0,0 +1,67 @@ +/* + * 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/CL/CLRuntimeContext.h" +#include "arm_compute/core/Validate.h" +#include "arm_compute/runtime/CL/CLHelpers.h" +#include "arm_compute/runtime/CL/CLScheduler.h" + +namespace arm_compute +{ +CLRuntimeContext::CLRuntimeContext() + : _gpu_owned_scheduler(support::cpp14::make_unique()), _gpu_scheduler(_gpu_owned_scheduler.get()), _symbols(), _core_context() +{ + _symbols.load_default(); + auto ctx_dev_err = create_opencl_context_and_device(); + ARM_COMPUTE_ERROR_ON_MSG(std::get<2>(ctx_dev_err) != CL_SUCCESS, "Failed to create OpenCL context"); + auto ctx = std::get<0>(ctx_dev_err); + auto dev = std::get<1>(ctx_dev_err); + cl::CommandQueue queue = cl::CommandQueue(ctx, dev); + _gpu_owned_scheduler->init(ctx, queue, dev, &_tuner); + const std::string cl_kernels_folder("./cl_kernels"); + _kernel_lib.init(cl_kernels_folder, ctx, dev); + _core_context = CLCoreRuntimeContext(&_kernel_lib, _gpu_owned_scheduler->context(), _gpu_owned_scheduler->queue()); +} + +CLKernelLibrary &CLRuntimeContext::kernel_library() +{ + return _kernel_lib; +} + +CLCoreRuntimeContext *CLRuntimeContext::core_runtime_context() +{ + return &_core_context; +} + +void CLRuntimeContext::set_gpu_scheduler(CLScheduler *scheduler) +{ + ARM_COMPUTE_ERROR_ON_NULLPTR(scheduler); + _gpu_scheduler = scheduler; +} + +CLScheduler *CLRuntimeContext::gpu_scheduler() +{ + return _gpu_scheduler; +} + +} // namespace arm_compute diff --git a/src/runtime/CL/CLScheduler.cpp b/src/runtime/CL/CLScheduler.cpp index 701ffe0ab1..e78eaa482f 100644 --- a/src/runtime/CL/CLScheduler.cpp +++ b/src/runtime/CL/CLScheduler.cpp @@ -23,13 +23,71 @@ */ #include "arm_compute/runtime/CL/CLScheduler.h" -#include "arm_compute/runtime/CL/CLHelpers.h" - +#include "arm_compute/core/CL/CLKernelLibrary.h" #include "arm_compute/core/CL/ICLKernel.h" +#include "arm_compute/runtime/CL/CLHelpers.h" #include "arm_compute/runtime/CL/CLTuner.h" #include "arm_compute/runtime/CL/tuners/Tuners.h" -using namespace arm_compute; +namespace arm_compute +{ +cl::Context &CLScheduler::context() +{ + ARM_COMPUTE_ERROR_ON(!_is_initialised); + _context = CLKernelLibrary::get().context(); + return _context; +} + +cl::CommandQueue &CLScheduler::queue() +{ + ARM_COMPUTE_ERROR_ON(!_is_initialised); + return _queue; +} + +GPUTarget CLScheduler::target() const +{ + return _target; +} + +void CLScheduler::set_queue(cl::CommandQueue queue) +{ + _queue = std::move(queue); +} + +void CLScheduler::set_target(GPUTarget target) +{ + _target = target; +} + +void CLScheduler::set_tuner(ICLTuner *tuner) +{ + _cl_tuner = tuner; +} + +void CLScheduler::sync() +{ + _queue.finish(); +} + +cl::Event CLScheduler::enqueue_sync_event() +{ + cl::Event event; + _queue.enqueueMarker(&event); + return event; +} + +void CLScheduler::tune_kernel_static(ICLKernel &kernel) +{ + if(_cl_tuner != nullptr) + { + _cl_tuner->tune_kernel_static(kernel); + } +} + +bool CLScheduler::is_initialised() const +{ + return _is_initialised; +} std::once_flag CLScheduler::_initialize_symbols; @@ -49,8 +107,9 @@ void CLScheduler::default_init_with_context(cl::Device &device, cl::Context &ctx { if(!_is_initialised) { - cl::CommandQueue queue = cl::CommandQueue(ctx, device); - CLKernelLibrary::get().init("./cl_kernels/", ctx, device); + const std::string cl_kernels_folder("./cl_kernels/"); + cl::CommandQueue queue = cl::CommandQueue(ctx, device); + CLKernelLibrary::get().init(cl_kernels_folder, ctx, device); init(ctx, queue, device, cl_tuner); _cl_default_static_tuner = tuners::TunerFactory::create_tuner(_target); _cl_tuner = (cl_tuner == nullptr) ? _cl_default_static_tuner.get() : cl_tuner; @@ -113,3 +172,4 @@ void CLScheduler::enqueue(ICLKernel &kernel, bool flush) _queue.flush(); } } +} // namespace arm_compute diff --git a/src/runtime/CL/CLTensor.cpp b/src/runtime/CL/CLTensor.cpp index 9bbf926b58..a6d0cf77ca 100644 --- a/src/runtime/CL/CLTensor.cpp +++ b/src/runtime/CL/CLTensor.cpp @@ -23,15 +23,21 @@ */ #include "arm_compute/runtime/CL/CLTensor.h" +#include "arm_compute/runtime/CL/CLRuntimeContext.h" #include "arm_compute/runtime/CL/CLScheduler.h" namespace arm_compute { -CLTensor::CLTensor() - : _allocator(this) +CLTensor::CLTensor(IRuntimeContext *ctx) + : _allocator(this, static_cast(ctx)), _ctx(static_cast(ctx)) { } +CLRuntimeContext *CLTensor::context() +{ + return _ctx; +} + TensorInfo *CLTensor::info() const { return &_allocator.info(); @@ -59,12 +65,12 @@ CLTensorAllocator *CLTensor::allocator() void CLTensor::map(bool blocking) { - ICLTensor::map(CLScheduler::get().queue(), blocking); + ICLTensor::map(_ctx == nullptr ? CLScheduler::get().queue() : _ctx->gpu_scheduler()->queue(), blocking); } void CLTensor::unmap() { - ICLTensor::unmap(CLScheduler::get().queue()); + ICLTensor::unmap(_ctx == nullptr ? CLScheduler::get().queue() : _ctx->gpu_scheduler()->queue()); } uint8_t *CLTensor::do_map(cl::CommandQueue &q, bool blocking) @@ -81,4 +87,4 @@ void CLTensor::associate_memory_group(arm_compute::IMemoryGroup *memory_group) { _allocator.set_associated_memory_group(memory_group); } -} // namespace arm_compute \ No newline at end of file +} // namespace arm_compute diff --git a/src/runtime/CL/CLTensorAllocator.cpp b/src/runtime/CL/CLTensorAllocator.cpp index 2b5fbb8241..eaf46d42ca 100644 --- a/src/runtime/CL/CLTensorAllocator.cpp +++ b/src/runtime/CL/CLTensorAllocator.cpp @@ -25,6 +25,7 @@ #include "arm_compute/core/Error.h" #include "arm_compute/core/TensorInfo.h" +#include "arm_compute/runtime/CL/CLRuntimeContext.h" #include "arm_compute/runtime/CL/CLScheduler.h" namespace arm_compute @@ -41,10 +42,10 @@ namespace * * @return A wrapped memory region */ -std::unique_ptr allocate_region(const cl::Context &context, size_t size, cl_uint alignment) +std::unique_ptr allocate_region(CLCoreRuntimeContext *ctx, size_t size, cl_uint alignment) { // Try fine-grain SVM - std::unique_ptr region = support::cpp14::make_unique(context, + std::unique_ptr region = support::cpp14::make_unique(ctx, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER, size, alignment); @@ -52,12 +53,12 @@ std::unique_ptr allocate_region(const cl::Context &context, siz // Try coarse-grain SVM in case of failure if(region != nullptr && region->ptr() == nullptr) { - region = support::cpp14::make_unique(context, CL_MEM_READ_WRITE, size, alignment); + region = support::cpp14::make_unique(ctx, CL_MEM_READ_WRITE, size, alignment); } // Try legacy buffer memory in case of failure if(region != nullptr && region->ptr() == nullptr) { - region = support::cpp14::make_unique(context, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size); + region = support::cpp14::make_unique(ctx, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, size); } return region; } @@ -103,8 +104,8 @@ void populate_quantization_info(CLFloatArray &scale, CLInt32Array &offset, const } } // namespace -CLTensorAllocator::CLTensorAllocator(IMemoryManageable *owner) - : _owner(owner), _associated_memory_group(nullptr), _memory(), _mapping(nullptr), _scale(), _offset() +CLTensorAllocator::CLTensorAllocator(IMemoryManageable *owner, CLRuntimeContext *ctx) + : _ctx(ctx), _owner(owner), _associated_memory_group(nullptr), _memory(), _mapping(nullptr), _scale(), _offset() { } @@ -129,7 +130,15 @@ void CLTensorAllocator::allocate() if(_associated_memory_group == nullptr) { // Perform memory allocation - _memory.set_owned_region(allocate_region(CLScheduler::get().context(), info().total_size(), 0)); + if(_ctx == nullptr) + { + auto legacy_ctx = CLCoreRuntimeContext(nullptr, CLScheduler::get().context(), CLScheduler::get().queue()); + _memory.set_owned_region(allocate_region(&legacy_ctx, info().total_size(), 0)); + } + else + { + _memory.set_owned_region(allocate_region(_ctx->core_runtime_context(), info().total_size(), 0)); + } } else { @@ -162,9 +171,17 @@ Status CLTensorAllocator::import_memory(cl::Buffer buffer) ARM_COMPUTE_RETURN_ERROR_ON(buffer.getInfo().get() != CLScheduler::get().context().get()); ARM_COMPUTE_RETURN_ERROR_ON(_associated_memory_group != nullptr); - _memory.set_owned_region(support::cpp14::make_unique(buffer)); - info().set_is_resizable(false); + if(_ctx == nullptr) + { + auto legacy_ctx = CLCoreRuntimeContext(nullptr, CLScheduler::get().context(), CLScheduler::get().queue()); + _memory.set_owned_region(support::cpp14::make_unique(buffer, &legacy_ctx)); + } + else + { + _memory.set_owned_region(support::cpp14::make_unique(buffer, _ctx->core_runtime_context())); + } + info().set_is_resizable(false); return Status{}; } @@ -179,13 +196,28 @@ void CLTensorAllocator::set_associated_memory_group(IMemoryGroup *associated_mem uint8_t *CLTensorAllocator::lock() { - return map(CLScheduler::get().queue(), true); + if(_ctx) + { + return map(_ctx->gpu_scheduler()->queue(), true); + } + else + { + return map(CLScheduler::get().queue(), true); + } } void CLTensorAllocator::unlock() { ARM_COMPUTE_ERROR_ON(_memory.region() == nullptr); - unmap(CLScheduler::get().queue(), reinterpret_cast(_memory.region()->buffer())); + if(_ctx) + { + unmap(_ctx->gpu_scheduler()->queue(), reinterpret_cast(_memory.region()->buffer())); + } + else + { + //Legacy singleton api + unmap(CLScheduler::get().queue(), reinterpret_cast(_memory.region()->buffer())); + } } uint8_t *CLTensorAllocator::map(cl::CommandQueue &q, bool blocking) diff --git a/src/runtime/CL/ICLSimpleFunction.cpp b/src/runtime/CL/ICLSimpleFunction.cpp index a1a56fd06c..fb8eba8aa4 100644 --- a/src/runtime/CL/ICLSimpleFunction.cpp +++ b/src/runtime/CL/ICLSimpleFunction.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017 ARM Limited. + * Copyright (c) 2016-2019 ARM Limited. * * SPDX-License-Identifier: MIT * @@ -24,20 +24,21 @@ #include "arm_compute/runtime/CL/ICLSimpleFunction.h" #include "arm_compute/core/Error.h" +#include "arm_compute/runtime/CL/CLHelpers.h" #include "arm_compute/runtime/CL/CLScheduler.h" using namespace arm_compute; -ICLSimpleFunction::ICLSimpleFunction() // NOLINT +ICLSimpleFunction::ICLSimpleFunction(CLRuntimeContext *ctx) // NOLINT : _kernel(), - _border_handler() + _border_handler(), + _ctx(ctx) { } void ICLSimpleFunction::run() { ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The child class didn't set the CL kernel or function isn't configured"); - - CLScheduler::get().enqueue(_border_handler, false); - CLScheduler::get().enqueue(*_kernel); + schedule_kernel_on_ctx(_ctx, &_border_handler, false); + schedule_kernel_on_ctx(_ctx, _kernel.get()); } diff --git a/src/runtime/CL/functions/CLActivationLayer.cpp b/src/runtime/CL/functions/CLActivationLayer.cpp index 2b66795cf9..00dbb71f4c 100644 --- a/src/runtime/CL/functions/CLActivationLayer.cpp +++ b/src/runtime/CL/functions/CLActivationLayer.cpp @@ -25,18 +25,21 @@ #include "arm_compute/core/CL/kernels/CLActivationLayerKernel.h" #include "arm_compute/core/Types.h" +#include "arm_compute/runtime/CL/CLRuntimeContext.h" #include "support/ToolchainSupport.h" namespace arm_compute { -CLActivationLayer::CLActivationLayer(void *ctx) +CLActivationLayer::CLActivationLayer(CLRuntimeContext *ctx) + : ICLSimpleFunction(ctx) { - ARM_COMPUTE_UNUSED(ctx); } void CLActivationLayer::configure(ICLTensor *input, ICLTensor *output, ActivationLayerInfo act_info) { - auto k = arm_compute::support::cpp14::make_unique(); + auto core_ctx = _ctx ? _ctx->core_runtime_context() : /* Legacy */ nullptr; + + auto k = arm_compute::support::cpp14::make_unique(core_ctx); k->configure(input, output, act_info); _kernel = std::move(k); } diff --git a/src/runtime/GLES_COMPUTE/GCTensor.cpp b/src/runtime/GLES_COMPUTE/GCTensor.cpp index 66c1abdb6d..e05eb4c4ae 100644 --- a/src/runtime/GLES_COMPUTE/GCTensor.cpp +++ b/src/runtime/GLES_COMPUTE/GCTensor.cpp @@ -26,7 +26,7 @@ namespace arm_compute { -GCTensor::GCTensor() +GCTensor::GCTensor(IRuntimeContext *) : _allocator(this) { } @@ -80,4 +80,4 @@ void GCTensor::do_unmap() { _allocator.unmap(); } -} // namespace arm_compute \ No newline at end of file +} // namespace arm_compute diff --git a/src/runtime/Tensor.cpp b/src/runtime/Tensor.cpp index de08efd731..8f7ecd6ffa 100644 --- a/src/runtime/Tensor.cpp +++ b/src/runtime/Tensor.cpp @@ -25,7 +25,7 @@ namespace arm_compute { -Tensor::Tensor() +Tensor::Tensor(IRuntimeContext *) : _allocator(this) { } @@ -54,4 +54,4 @@ void Tensor::associate_memory_group(IMemoryGroup *memory_group) { _allocator.set_associated_memory_group(memory_group); } -} // namespace arm_compute \ No newline at end of file +} // namespace arm_compute diff --git a/tests/Globals.h b/tests/Globals.h index 569b1a31c6..989fdfdcd4 100644 --- a/tests/Globals.h +++ b/tests/Globals.h @@ -25,7 +25,7 @@ #define __ARM_COMPUTE_TEST_GLOBALS_H__ #include "tests/AssetsLibrary.h" -#include "tests/ParametersLibrary.h" +#include "tests/framework/ParametersLibrary.h" #include diff --git a/tests/ParametersLibrary.cpp b/tests/ParametersLibrary.cpp deleted file mode 100644 index 16152c8482..0000000000 --- a/tests/ParametersLibrary.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 cpu_ctx) -{ - _cpu_ctx = std::move(cpu_ctx); -} - -template <> -typename ContextType::type *ParametersLibrary::get_ctx() -{ - return _cpu_ctx.get(); -} -} // namespace test -} // namespace arm_compute diff --git a/tests/ParametersLibrary.h b/tests/ParametersLibrary.h deleted file mode 100644 index a99be46d3f..0000000000 --- a/tests/ParametersLibrary.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 - -namespace arm_compute -{ -namespace test -{ -// Return type trait helper -template -struct ContextType -{ - using type = void; -}; -template <> -struct ContextType -{ - 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 cpu_ctx); - /** Get context given a tensor type - * - * @tparam TensorType - * - * @return Pointer to the context - */ - template - typename ContextType::type *get_ctx() - { - return nullptr; - } - -private: - std::unique_ptr _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 ea70fffe3a..3bb6060951 100644 --- a/tests/Utils.h +++ b/tests/Utils.h @@ -520,14 +520,15 @@ inline bool is_in_valid_region(const ValidRegion &valid_region, Coordinates coor * @param[in] num_channels (Optional) Number of channels. * @param[in] quantization_info (Optional) Quantization info for asymmetric quantized types. * @param[in] data_layout (Optional) Data layout. Default is NCHW. + * @param[in] ctx (Optional) Pointer to the runtime context. * * @return Initialized tensor of given type. */ template inline T create_tensor(const TensorShape &shape, DataType data_type, int num_channels = 1, - QuantizationInfo quantization_info = QuantizationInfo(), DataLayout data_layout = DataLayout::NCHW) + QuantizationInfo quantization_info = QuantizationInfo(), DataLayout data_layout = DataLayout::NCHW, IRuntimeContext *ctx = nullptr) { - T tensor; + T tensor(ctx); TensorInfo info(shape, num_channels, data_type); info.set_quantization_info(quantization_info); info.set_data_layout(data_layout); @@ -540,15 +541,16 @@ inline T create_tensor(const TensorShape &shape, DataType data_type, int num_cha * * @param[in] shape Tensor shape. * @param[in] format Format type. + * @param[in] ctx (Optional) Pointer to the runtime context. * * @return Initialized tensor of given type. */ template -inline T create_tensor(const TensorShape &shape, Format format) +inline T create_tensor(const TensorShape &shape, Format format, IRuntimeContext *ctx = nullptr) { TensorInfo info(shape, format); - T tensor; + T tensor(ctx); tensor.allocator()->init(info); return tensor; diff --git a/tests/framework/Framework.cpp b/tests/framework/Framework.cpp index fbc2456047..5d1600e083 100644 --- a/tests/framework/Framework.cpp +++ b/tests/framework/Framework.cpp @@ -25,8 +25,12 @@ #include "arm_compute/runtime/Scheduler.h" #include "support/ToolchainSupport.h" +#include "tests/framework/ParametersLibrary.h" + #ifdef ARM_COMPUTE_CL +#include "arm_compute/runtime/CL/CLRuntimeContext.h" #include "arm_compute/runtime/CL/CLScheduler.h" + #endif /* ARM_COMPUTE_CL */ #include @@ -38,6 +42,8 @@ namespace arm_compute { namespace test { +std::unique_ptr parameters; + namespace framework { std::unique_ptr instruments_info; @@ -558,17 +564,23 @@ bool Framework::run() // Every 100 tests, reset the OpenCL context to release the allocated memory if(opencl_is_available() && (id_run_test % 100) == 0) { - auto ctx_properties = CLScheduler::get().context().getInfo(nullptr); - auto queue_properties = CLScheduler::get().queue().getInfo(nullptr); - - cl::Context new_ctx = cl::Context(CL_DEVICE_TYPE_DEFAULT, ctx_properties.data()); - cl::CommandQueue new_queue = cl::CommandQueue(new_ctx, CLKernelLibrary::get().get_device(), queue_properties); - CLKernelLibrary::get().clear_programs_cache(); - CLScheduler::get().set_context(new_ctx); - CLScheduler::get().set_queue(new_queue); + auto cl_ctx = support::cpp14::make_unique(); + assert(cl_ctx != nullptr); + CLScheduler *gpu_scheduler = cl_ctx->gpu_scheduler(); + assert(gpu_scheduler != nullptr); + { + // Legacy singletons API: This has been deprecated and the singletons will be removed + // Setup singleton for backward compatibility + CLScheduler::get().init(gpu_scheduler->context(), gpu_scheduler->queue(), cl_ctx->kernel_library().get_device()); + } + if(parameters) + { + parameters->set_gpu_ctx(std::move(cl_ctx)); + } } #endif // ARM_COMPUTE_CL + run_test(test_info, *test_factory); ++id_run_test; diff --git a/tests/framework/ParametersLibrary.cpp b/tests/framework/ParametersLibrary.cpp new file mode 100644 index 0000000000..65a09eeb64 --- /dev/null +++ b/tests/framework/ParametersLibrary.cpp @@ -0,0 +1,54 @@ +/* + * 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/framework/ParametersLibrary.h" + +namespace arm_compute +{ +namespace test +{ +void ParametersLibrary::set_cpu_ctx(std::unique_ptr cpu_ctx) +{ + _cpu_ctx = std::move(cpu_ctx); +} + +void ParametersLibrary::set_gpu_ctx(std::unique_ptr gpu_ctx) +{ + _gpu_ctx = std::move(gpu_ctx); +} + +template <> +typename ContextType::type *ParametersLibrary::get_ctx() +{ + return _cpu_ctx.get(); +} + +#if ARM_COMPUTE_CL +template <> +typename ContextType::type *ParametersLibrary::get_ctx() +{ + return static_cast::type *>(_gpu_ctx.get()); +} +#endif /* ARM_COMPUTE_CL */ +} // namespace test +} // namespace arm_compute diff --git a/tests/framework/ParametersLibrary.h b/tests/framework/ParametersLibrary.h new file mode 100644 index 0000000000..4079ab25b9 --- /dev/null +++ b/tests/framework/ParametersLibrary.h @@ -0,0 +1,105 @@ +/* + * 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" +#if ARM_COMPUTE_CL +#include "arm_compute/runtime/CL/CLRuntimeContext.h" +#include "arm_compute/runtime/CL/CLTensor.h" +#endif /* ARM_COMPUTE_CL */ +#ifdef ARM_COMPUTE_GC +#include "arm_compute/runtime/GLES_COMPUTE/GCTensor.h" +#endif /* ARM_COMPUTE_GC */ + +#include + +namespace arm_compute +{ +namespace test +{ +// Return type trait helper +template +struct ContextType +{ + using type = void; +}; +template <> +struct ContextType +{ + using type = IRuntimeContext; +}; + +#if ARM_COMPUTE_CL +template <> +struct ContextType +{ + using type = CLRuntimeContext; +}; +#endif /* ARM_COMPUTE_CL */ + +#ifdef ARM_COMPUTE_GC +template <> +struct ContextType +{ + using type = IRuntimeContext; +}; +#endif /* ARM_COMPUTE_GC */ + +/** 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 cpu_ctx); + /** Set gpu context to be used by the tests + * + * @param[in] gpu_ctx GPU context to use + */ + void set_gpu_ctx(std::unique_ptr gpu_ctx); + /** Get context given a tensor type + * + * @tparam TensorType + * + * @return Pointer to the context + */ + template + typename ContextType::type *get_ctx() + { + return nullptr; + } + +private: + std::unique_ptr _cpu_ctx{ nullptr }; + std::unique_ptr _gpu_ctx{ nullptr }; +}; +} // namespace test +} // namespace arm_compute +#endif //__ARM_COMPUTE_TEST_PARAMETERS_LIBRARY_H__ diff --git a/tests/main.cpp b/tests/main.cpp index 01741939a0..415dba0405 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -23,11 +23,11 @@ */ #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" #include "tests/framework/Macros.h" +#include "tests/framework/ParametersLibrary.h" #include "tests/framework/Profiler.h" #include "tests/framework/command_line/CommonOptions.h" #include "tests/framework/instruments/Instruments.h" @@ -74,8 +74,8 @@ namespace arm_compute { namespace test { -std::unique_ptr library; -std::unique_ptr parameters; +std::unique_ptr library; +extern std::unique_ptr parameters; } // namespace test } // namespace arm_compute @@ -92,17 +92,6 @@ bool file_exists(const std::string &filename) int main(int argc, char **argv) { -#ifdef ARM_COMPUTE_CL - CLTuner cl_tuner(false); - if(opencl_is_available()) - { - auto ctx_dev_err = create_opencl_context_and_device(); - ARM_COMPUTE_ERROR_ON_MSG(std::get<2>(ctx_dev_err) != CL_SUCCESS, "Failed to create OpenCL context"); - CLScheduler::get() - .default_init_with_context(std::get<1>(ctx_dev_err), std::get<0>(ctx_dev_err), &cl_tuner); - } -#endif /* ARM_COMPUTE_CL */ - #ifdef ARM_COMPUTE_GC GCScheduler::get().default_init(); #endif /* ARM_COMPUTE_GC */ @@ -185,6 +174,20 @@ int main(int argc, char **argv) parameters->set_cpu_ctx(std::move(cpu_ctx)); #ifdef ARM_COMPUTE_CL + CLTuner cl_tuner(false); + // Create GPU context + auto cl_ctx = support::cpp14::make_unique(); + assert(cl_ctx != nullptr); + CLScheduler *gpu_scheduler = cl_ctx->gpu_scheduler(); + assert(gpu_scheduler != nullptr); + const auto device_version = cl_ctx->kernel_library().get_device_version(); + { + // Legacy singletons API: This has been deprecated and the singletons will be removed + // Setup singleton for backward compatibility + CLScheduler::get().init(gpu_scheduler->context(), gpu_scheduler->queue(), cl_ctx->kernel_library().get_device(), &cl_tuner); + } + parameters->set_gpu_ctx(std::move(cl_ctx)); + if(enable_tuner->is_set()) { cl_tuner.set_tune_new_kernels(enable_tuner->value()); @@ -222,7 +225,7 @@ int main(int argc, char **argv) #ifdef ARM_COMPUTE_CL if(opencl_is_available()) { - p->print_entry("CL_DEVICE_VERSION", CLKernelLibrary::get().get_device_version()); + p->print_entry("CL_DEVICE_VERSION", device_version); } else { diff --git a/tests/validation/CL/ActivationLayer.cpp b/tests/validation/CL/ActivationLayer.cpp index 250777d541..a17ad9b269 100644 --- a/tests/validation/CL/ActivationLayer.cpp +++ b/tests/validation/CL/ActivationLayer.cpp @@ -95,15 +95,18 @@ TEST_SUITE(ActivationLayer) DATA_TEST_CASE(Configuration, framework::DatasetMode::ALL, combine(combine(datasets::SmallShapes(), CNNDataTypes), framework::dataset::make("InPlace", { false, true })), shape, data_type, in_place) { + // Create context + auto ctx = parameters->get_ctx(); + // Create tensors - CLTensor src = create_tensor(shape, data_type, 1); - CLTensor dst = create_tensor(shape, data_type, 1); + CLTensor src = create_tensor(shape, data_type, 1, QuantizationInfo(), DataLayout::NCHW, ctx); + CLTensor dst = create_tensor(shape, data_type, 1, QuantizationInfo(), DataLayout::NCHW, ctx); ARM_COMPUTE_EXPECT(src.info()->is_resizable(), framework::LogLevel::ERRORS); ARM_COMPUTE_EXPECT(dst.info()->is_resizable(), framework::LogLevel::ERRORS); // Create and configure function - CLActivationLayer act_layer; + CLActivationLayer act_layer(ctx); if(in_place) { diff --git a/tests/validation/fixtures/ActivationLayerFixture.h b/tests/validation/fixtures/ActivationLayerFixture.h index 8fa74979a8..f6d43ddd89 100644 --- a/tests/validation/fixtures/ActivationLayerFixture.h +++ b/tests/validation/fixtures/ActivationLayerFixture.h @@ -29,9 +29,9 @@ #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/framework/ParametersLibrary.h" #include "tests/validation/Helpers.h" #include "tests/validation/reference/ActivationLayer.h" @@ -47,6 +47,11 @@ template get_ctx()) + { + } + template void setup(TensorShape shape, bool in_place, ActivationLayerInfo::ActivationFunction function, float alpha_beta, DataType data_type, QuantizationInfo quantization_info) { @@ -90,12 +95,13 @@ protected: TensorType compute_target(const TensorShape &shape, ActivationLayerInfo info) { + auto ctx = parameters->get_ctx(); // Create tensors - TensorType src = create_tensor(shape, _data_type, 1, _input_quantization_info); - TensorType dst = create_tensor(shape, _data_type, 1, _output_quantization_info); + TensorType src = create_tensor(shape, _data_type, 1, _input_quantization_info, DataLayout::NCHW, ctx); + TensorType dst = create_tensor(shape, _data_type, 1, _output_quantization_info, DataLayout::NCHW, ctx); // Create and configure function - FunctionType act_layer(parameters->get_ctx()); + FunctionType act_layer(ctx); TensorType *dst_ptr = _in_place ? nullptr : &dst; diff --git a/utils/Utils.cpp b/utils/Utils.cpp index b0e162accd..8cc3fcf9b0 100644 --- a/utils/Utils.cpp +++ b/utils/Utils.cpp @@ -24,6 +24,7 @@ #include "Utils.h" #ifdef ARM_COMPUTE_CL +#include "arm_compute/core/CL/CLKernelLibrary.h" #include "arm_compute/runtime/CL/CLScheduler.h" #endif /* ARM_COMPUTE_CL */ -- cgit v1.2.1