[GPU] 2.0 plugin api impl (#18920)

This commit is contained in:
Vladimir Paramuzov authored and GitHub committed 2023-09-12 11:13:59 +04:00
1 parent 8e0d8dd36b
commit 47fe50ca35
90 files changed
+3413 -6313

No files matched your search

@@ -360,9 +360,9 @@ TEST_P(ov_remote_context_ocl, create_remote_tensor_nv12_from_ocl_image2D) {
const int height = 480;
const int width = 640;
ov_shape_t shape_y = {0, nullptr};
int64_t dims_y[4] = {1, 1, height, width};
int64_t dims_y[4] = {1, height, width, 1};
ov_shape_t shape_uv = {0, nullptr};
int64_t dims_uv[4] = {1, 2, height / 2, width / 2};
int64_t dims_uv[4] = {1, height / 2, width / 2, 2};
cl_int err;
cl_image_format image_format;
@@ -555,9 +555,9 @@ TEST_P(ov_remote_context_ocl, remote_tensor_nv12_inference) {
EXPECT_NE(nullptr, context);
ov_shape_t shape_y = {0, nullptr};
int64_t dims_y[4] = {1, 1, height, width};
int64_t dims_y[4] = {1, height, width, 1};
ov_shape_t shape_uv = {0, nullptr};
int64_t dims_uv[4] = {1, 2, height / 2, width / 2};
int64_t dims_uv[4] = {1, height / 2, width / 2, 2};
cl_int err;
cl_image_format image_format;
@@ -151,12 +151,12 @@ protected:
const std::function<void(ov::SoPtr<ov::ITensor>& tensor)>& allocate_callback);
std::unordered_map<std::shared_ptr<ov::descriptor::Tensor>, std::vector<ov::SoPtr<ov::ITensor>>> m_batched_tensors;
ov::SoPtr<ov::ITensor>& get_tensor_ptr(const ov::Output<const ov::Node>& port) const;
private:
std::shared_ptr<const ov::ICompiledModel> m_compiled_model;
// Mutable to return reference to ov::Tensor
mutable std::unordered_map<std::shared_ptr<ov::descriptor::Tensor>, ov::SoPtr<ov::ITensor>> m_tensors;
ov::SoPtr<ov::ITensor>& get_tensor_ptr(const ov::Output<const ov::Node>& port) const;
/**
* @brief Finds input or output port
@@ -67,7 +67,7 @@ OPENVINO_RUNTIME_API ov::SoPtr<ov::ITensor> get_tensor_impl(const ov::Tensor& te
IE_SUPPRESS_DEPRECATED_START
/** @cond INTERNAL */
ov::SoPtr<ITensor> make_tensor(const std::shared_ptr<InferenceEngine::Blob>& tensor);
ov::SoPtr<ITensor> make_tensor(const std::shared_ptr<InferenceEngine::Blob>& tensor, bool unwrap = false);
const InferenceEngine::Blob* get_hardware_blob(const InferenceEngine::Blob* blob);
InferenceEngine::Blob* get_hardware_blob(InferenceEngine::Blob* blob);
+184
View File
@@ -0,0 +1,184 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "ie_ngraph_utils.hpp"
#include "ie_remote_blob.hpp"
#include "ie_remote_context.hpp"
#include "openvino/runtime/iremote_context.hpp"
namespace ov {
namespace legacy_convert {
INFERENCE_ENGINE_API_CPP(ov::SoPtr<ov::IRemoteContext>)
convert_remote_context(const std::shared_ptr<InferenceEngine::RemoteContext>& context);
INFERENCE_ENGINE_API_CPP(ie::Blob*) get_hardware_blob(ie::Blob* blob);
class INFERENCE_ENGINE_API_CLASS(TensorHolder) {
public:
TensorHolder(ov::SoPtr<ov::ITensor> tensor) : _tensor(tensor) {}
const ov::SoPtr<ov::ITensor>& get_tensor() const {
return _tensor;
}
private:
ov::SoPtr<ov::ITensor> _tensor;
};
} // namespace legacy_convert
/**
* @brief Tensor what contains InferenceEngine::RemoteBlob inside
* Blob owns the memory
*/
class INFERENCE_ENGINE_API_CLASS(RemoteBlobTensor) : public IRemoteTensor {
mutable element::Type m_type;
mutable Shape m_shape;
mutable Strides m_strides;
mutable ov::AnyMap m_properties;
mutable std::string m_dev_name;
public:
std::shared_ptr<ie::RemoteBlob> blob;
RemoteBlobTensor(const InferenceEngine::RemoteBlob::Ptr& blob) : blob{blob} {
OPENVINO_ASSERT(blob);
m_shape = blob->getTensorDesc().getBlockingDesc().getBlockDims();
}
const element::Type& get_element_type() const override {
m_type = InferenceEngine::details::convertPrecision(blob->getTensorDesc().getPrecision());
return m_type;
}
void set_shape(ov::Shape shape) override {
blob->setShape({shape.begin(), shape.end()});
}
const Shape& get_shape() const override {
m_shape = blob->getTensorDesc().getBlockingDesc().getBlockDims();
return m_shape;
}
const Strides& get_strides() const override {
OPENVINO_ASSERT(get_element_type().bitwidth() >= 8,
"Could not get strides for types with bitwidths less then 8 bit. Tensor type: ",
get_element_type());
const auto& element_strides = blob->getTensorDesc().getBlockingDesc().getStrides();
const size_t elem_size = get_element_type().size();
m_strides.clear();
m_strides.resize(element_strides.size());
std::transform(element_strides.begin(), element_strides.end(), m_strides.begin(), [&elem_size](size_t stride) {
return stride * elem_size;
});
return m_strides;
}
size_t get_size() const override {
return blob->size();
}
size_t get_byte_size() const override {
return blob->byteSize();
}
const AnyMap& get_properties() const override {
m_properties = blob->getParams();
return m_properties;
}
const std::string& get_device_name() const override {
m_dev_name = blob->getDeviceName();
return m_dev_name;
}
};
/**
* @brief Create InferenceEngine::RemoteBlob from the Tensor
*/
class INFERENCE_ENGINE_API_CLASS(TensorRemoteBlob) : public ie::RemoteBlob, public ov::legacy_convert::TensorHolder {
public:
TensorRemoteBlob(const ov::SoPtr<ITensor>& tensor, ie::TensorDesc desc)
: ie::RemoteBlob{desc},
ov::legacy_convert::TensorHolder(tensor) {
OPENVINO_ASSERT(this->get_tensor());
}
std::shared_ptr<ov::IRemoteTensor> cast_tensor() const {
auto remote = std::dynamic_pointer_cast<ov::IRemoteTensor>(get_tensor()._ptr);
OPENVINO_ASSERT(remote);
return remote;
}
AnyMap getParams() const override {
return cast_tensor()->get_properties();
}
std::string getDeviceName() const noexcept override {
try {
return cast_tensor()->get_device_name();
} catch (...) {
return {};
}
}
std::shared_ptr<ie::RemoteContext> getContext() const noexcept override {
return {};
}
void allocate() noexcept override {}
bool deallocate() noexcept override {
return true;
}
ie::LockedMemory<void> buffer() noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<const void> cbuffer() const noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<void> rwmap() noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<const void> rmap() const noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<void> wmap() noexcept override {
return {nullptr, nullptr, 0};
}
const std::shared_ptr<ie::IAllocator>& getAllocator() const noexcept override {
return m_allocator;
}
void* getHandle() const noexcept override {
return nullptr;
}
using TensorHolder::get_tensor;
private:
std::shared_ptr<ie::IAllocator> m_allocator;
};
} // namespace ov
namespace InferenceEngine {
class INFERENCE_ENGINE_API_CLASS(IRemoteContextWrapper) : public ov::IRemoteContext {
private:
std::shared_ptr<InferenceEngine::RemoteContext> m_context;
mutable std::string m_name;
mutable ov::AnyMap m_params;
public:
IRemoteContextWrapper(const std::shared_ptr<InferenceEngine::RemoteContext>& context) : m_context(context) {}
virtual ~IRemoteContextWrapper() = default;
const std::shared_ptr<InferenceEngine::RemoteContext>& get_context();
const std::string& get_device_name() const override;
const ov::AnyMap& get_property() const override;
ov::SoPtr<ov::IRemoteTensor> create_tensor(const ov::element::Type& type,
const ov::Shape& shape,
const ov::AnyMap& params = {}) override;
ov::SoPtr<ov::ITensor> create_host_tensor(const ov::element::Type type, const ov::Shape& shape) override;
};
} // namespace InferenceEngine
@@ -139,7 +139,7 @@ public:
* @param target_tile_id Desired tile id within given context for multi-tile system. Default value (-1) means
* that root device should be used
*/
D3DContext(Core& core, ID3D11Device* device, int target_tile_id = -1) : ClContext(core, (cl_context) nullptr) {
D3DContext(Core& core, ID3D11Device* device, int target_tile_id = -1) : ClContext() {
// clang-format off
AnyMap context_params = {
{ov::intel_gpu::context_type.name(), ov::intel_gpu::ContextType::VA_SHARED},
@@ -177,6 +177,11 @@ protected:
*/
static constexpr const char* device_name = "GPU";
/**
* @brief Default constructor which can be used in derived classes to avoid multiple create_context() calls
*/
ClContext() = default;
public:
// Needed to make create_tensor overloads from base class visible for user
using RemoteContext::create_tensor;
@@ -104,7 +104,7 @@ public:
* @param target_tile_id Desired tile id within given context for multi-tile system. Default value (-1) means
* that root device should be used
*/
VAContext(Core& core, VADisplay device, int target_tile_id = -1) : ClContext(core, (cl_context) nullptr) {
VAContext(Core& core, VADisplay device, int target_tile_id = -1) : ClContext() {
AnyMap context_params = {{ov::intel_gpu::context_type.name(), ov::intel_gpu::ContextType::VA_SHARED},
{ov::intel_gpu::va_device.name(), static_cast<gpu_handle_param>(device)},
{ov::intel_gpu::tile_id.name(), target_tile_id}};
+33 -43
View File
@@ -215,7 +215,7 @@ public:
}
void SetState(const InferenceEngine::Blob::Ptr& newState) override {
m_state->set_state(ov::make_tensor(newState));
m_state->set_state(ov::make_tensor(newState, true));
}
InferenceEngine::Blob::CPtr GetState() const override {
@@ -542,7 +542,7 @@ public:
void SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr& data) override {
try {
m_request->set_tensor(find_port(name), ov::make_tensor(data));
m_request->set_tensor(find_port(name), ov::make_tensor(data, true));
} catch (const ov::Exception& ex) {
const std::string what = ex.what();
if (what.find("Failed to set tensor") != std::string::npos) {
@@ -556,7 +556,7 @@ public:
try {
std::vector<ov::SoPtr<ov::ITensor>> tensors;
for (const auto& blob : blobs) {
tensors.emplace_back(ov::make_tensor(blob));
tensors.emplace_back(ov::make_tensor(blob, true));
}
m_request->set_tensors(find_port(name), tensors);
} catch (const ov::Exception& ex) {
@@ -860,50 +860,40 @@ ov::SoPtr<::ov::IAsyncInferRequest> ov::legacy_convert::convert_infer_request(
}
namespace InferenceEngine {
const std::shared_ptr<InferenceEngine::RemoteContext>& IRemoteContextWrapper::get_context() {
return m_context;
}
class IRemoteContextWrapper : public ov::IRemoteContext {
private:
std::shared_ptr<InferenceEngine::RemoteContext> m_context;
mutable std::string m_name;
mutable ov::AnyMap m_params;
const std::string& IRemoteContextWrapper::get_device_name() const {
m_name = m_context->getDeviceName();
return m_name;
}
public:
IRemoteContextWrapper(const std::shared_ptr<InferenceEngine::RemoteContext>& context) : m_context(context) {}
virtual ~IRemoteContextWrapper() = default;
const std::shared_ptr<InferenceEngine::RemoteContext>& get_context() {
return m_context;
}
const std::string& get_device_name() const override {
m_name = m_context->getDeviceName();
return m_name;
}
const ov::AnyMap& IRemoteContextWrapper::get_property() const {
m_params = m_context->getParams();
return m_params;
}
const ov::AnyMap& get_property() const override {
m_params = m_context->getParams();
return m_params;
}
ov::SoPtr<ov::IRemoteTensor> IRemoteContextWrapper::create_tensor(const ov::element::Type& type,
const ov::Shape& shape,
const ov::AnyMap& params) {
InferenceEngine::TensorDesc desc(InferenceEngine::details::convertPrecision(type),
shape,
InferenceEngine::TensorDesc::getLayoutByDims(shape));
auto blob = m_context->CreateBlob(desc, params);
blob->allocate();
auto tensor = ov::make_tensor(blob);
return {std::dynamic_pointer_cast<ov::IRemoteTensor>(tensor._ptr), tensor._so};
}
ov::SoPtr<ov::IRemoteTensor> create_tensor(const ov::element::Type& type,
const ov::Shape& shape,
const ov::AnyMap& params = {}) override {
InferenceEngine::TensorDesc desc(InferenceEngine::details::convertPrecision(type),
shape,
InferenceEngine::TensorDesc::getLayoutByDims(shape));
auto blob = m_context->CreateBlob(desc, params);
blob->allocate();
auto tensor = ov::make_tensor(blob);
return {std::dynamic_pointer_cast<ov::IRemoteTensor>(tensor._ptr), tensor._so};
}
ov::SoPtr<ov::ITensor> create_host_tensor(const ov::element::Type type, const ov::Shape& shape) override {
InferenceEngine::TensorDesc desc(InferenceEngine::details::convertPrecision(type),
shape,
InferenceEngine::TensorDesc::getLayoutByDims(shape));
auto blob = m_context->CreateHostBlob(desc);
blob->allocate();
return ov::make_tensor(blob);
}
};
ov::SoPtr<ov::ITensor> IRemoteContextWrapper::create_host_tensor(const ov::element::Type type, const ov::Shape& shape) {
InferenceEngine::TensorDesc desc(InferenceEngine::details::convertPrecision(type),
shape,
InferenceEngine::TensorDesc::getLayoutByDims(shape));
auto blob = m_context->CreateHostBlob(desc);
blob->allocate();
return ov::make_tensor(blob);
}
} // namespace InferenceEngine
+1 -2
View File
@@ -15,6 +15,7 @@
#include "openvino/runtime/icompiled_model.hpp"
#include "openvino/runtime/iplugin.hpp"
#include "openvino/runtime/iremote_context.hpp"
#include "remote_utils.hpp"
namespace ov {
namespace legacy_convert {
@@ -40,11 +41,9 @@ ov::SoPtr<::ov::IAsyncInferRequest> convert_infer_request(
const std::string& plugin_name = "");
std::shared_ptr<InferenceEngine::RemoteContext> convert_remote_context(const ov::SoPtr<ov::IRemoteContext>& context);
ov::SoPtr<ov::IRemoteContext> convert_remote_context(const std::shared_ptr<InferenceEngine::RemoteContext>& context);
std::vector<ov::Extension::Ptr> convert_extension(const std::vector<InferenceEngine::IExtensionPtr>& exts);
std::vector<InferenceEngine::IExtensionPtr> convert_extension(const std::vector<ov::Extension::Ptr>& exts);
} // namespace legacy_convert
} // namespace ov
+7 -129
View File
@@ -11,6 +11,7 @@
#include "ie_remote_blob.hpp"
#include "openvino/runtime/iremote_tensor.hpp"
#include "openvino/runtime/properties.hpp"
#include "remote_utils.hpp"
#ifdef PROXY_PLUGIN_ENABLED
# include "openvino/proxy/plugin.hpp"
#endif
@@ -371,131 +372,6 @@ public:
}
};
/**
* @brief Tensor what contains InferenceEngine::RemoteBlob inside
* Blob owns the memory
*/
class RemoteBlobTensor : public IRemoteTensor {
mutable element::Type m_type;
mutable Shape m_shape;
mutable Strides m_strides;
mutable ov::AnyMap m_properties;
mutable std::string m_dev_name;
public:
std::shared_ptr<ie::RemoteBlob> blob;
RemoteBlobTensor(const InferenceEngine::RemoteBlob::Ptr& blob) : blob{blob} {
OPENVINO_ASSERT(blob);
m_shape = blob->getTensorDesc().getBlockingDesc().getBlockDims();
}
const element::Type& get_element_type() const override {
m_type = InferenceEngine::details::convertPrecision(blob->getTensorDesc().getPrecision());
return m_type;
}
void set_shape(ov::Shape shape) override {
blob->setShape({shape.begin(), shape.end()});
}
const Shape& get_shape() const override {
m_shape = blob->getTensorDesc().getBlockingDesc().getBlockDims();
return m_shape;
}
const Strides& get_strides() const override {
OPENVINO_ASSERT(get_element_type().bitwidth() >= 8,
"Could not get strides for types with bitwidths less then 8 bit. Tensor type: ",
get_element_type());
const auto& element_strides = blob->getTensorDesc().getBlockingDesc().getStrides();
const size_t elem_size = get_element_type().size();
m_strides.clear();
m_strides.resize(element_strides.size());
std::transform(element_strides.begin(), element_strides.end(), m_strides.begin(), [&elem_size](size_t stride) {
return stride * elem_size;
});
return m_strides;
}
size_t get_size() const override {
return blob->size();
}
size_t get_byte_size() const override {
return blob->byteSize();
}
const AnyMap& get_properties() const override {
m_properties = blob->getParams();
return m_properties;
}
const std::string& get_device_name() const override {
m_dev_name = blob->getDeviceName();
return m_dev_name;
}
};
/**
* @brief Create InferenceEngine::RemoteBlob from the Tensor
*/
class TensorRemoteBlob : public ie::RemoteBlob {
public:
TensorRemoteBlob(const ov::SoPtr<ITensor>& tensor, ie::TensorDesc desc) : ie::RemoteBlob{desc}, tensor{tensor} {
OPENVINO_ASSERT(this->tensor);
}
std::shared_ptr<ov::IRemoteTensor> cast_tensor() const {
auto remote = std::dynamic_pointer_cast<ov::IRemoteTensor>(tensor._ptr);
OPENVINO_ASSERT(remote);
return remote;
}
AnyMap getParams() const override {
return cast_tensor()->get_properties();
}
std::string getDeviceName() const noexcept override {
try {
return cast_tensor()->get_device_name();
} catch (...) {
return {};
}
}
std::shared_ptr<ie::RemoteContext> getContext() const noexcept override {
return {};
}
void allocate() noexcept override {}
bool deallocate() noexcept override {
return true;
}
ie::LockedMemory<void> buffer() noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<const void> cbuffer() const noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<void> rwmap() noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<const void> rmap() const noexcept override {
return {nullptr, nullptr, 0};
}
ie::LockedMemory<void> wmap() noexcept override {
return {nullptr, nullptr, 0};
}
const std::shared_ptr<ie::IAllocator>& getAllocator() const noexcept override {
return m_allocator;
}
void* getHandle() const noexcept override {
return nullptr;
}
ov::SoPtr<ITensor> tensor;
private:
std::shared_ptr<ie::IAllocator> m_allocator;
};
/**
* @brief Create InferenceEngine::TBlob<T> from the tensor
*
@@ -530,15 +406,17 @@ public:
ov::SoPtr<ITensor> tensor;
};
ov::SoPtr<ITensor> make_tensor(const std::shared_ptr<ie::Blob>& blob) {
ov::SoPtr<ITensor> make_tensor(const std::shared_ptr<ie::Blob>& blob, bool unwrap) {
#define ELSE_IF(type) \
else if (auto tblob = dynamic_cast<const TensorMemoryBlob<type>*>(blob.get())) { \
return tblob->tensor; \
}
if (blob == nullptr) {
return {};
} else if (unwrap && std::dynamic_pointer_cast<legacy_convert::TensorHolder>(blob) != nullptr) {
return std::dynamic_pointer_cast<legacy_convert::TensorHolder>(blob)->get_tensor();
} else if (auto remote_blob = std::dynamic_pointer_cast<TensorRemoteBlob>(blob)) {
return remote_blob->tensor;
return remote_blob->get_tensor();
} else if (auto remote_blob = std::dynamic_pointer_cast<InferenceEngine::RemoteBlob>(blob)) {
return {std::make_shared<RemoteBlobTensor>(remote_blob), nullptr};
}
@@ -564,7 +442,7 @@ ov::SoPtr<ITensor> make_tensor(const std::shared_ptr<ie::Blob>& blob) {
ie::Blob* get_hardware_blob(ie::Blob* blob) {
#ifdef PROXY_PLUGIN_ENABLED
if (auto remote_blob = dynamic_cast<TensorRemoteBlob*>(blob)) {
const auto& tensor = ov::proxy::get_hardware_tensor(remote_blob->tensor);
const auto& tensor = ov::proxy::get_hardware_tensor(remote_blob->get_tensor());
if (auto blob_tensor = std::dynamic_pointer_cast<BlobTensor>(tensor._ptr)) {
return blob_tensor->blob.get();
} else if (auto blob_tensor = std::dynamic_pointer_cast<RemoteBlobTensor>(tensor._ptr)) {
@@ -579,7 +457,7 @@ ie::Blob* get_hardware_blob(ie::Blob* blob) {
const ie::Blob* get_hardware_blob(const ie::Blob* blob) {
#ifdef PROXY_PLUGIN_ENABLED
if (auto remote_blob = dynamic_cast<const TensorRemoteBlob*>(blob)) {
const auto& tensor = ov::proxy::get_hardware_tensor(remote_blob->tensor);
const auto& tensor = ov::proxy::get_hardware_tensor(remote_blob->get_tensor());
if (auto blob_tensor = std::dynamic_pointer_cast<BlobTensor>(tensor._ptr)) {
return blob_tensor->blob.get();
} else if (auto blob_tensor = std::dynamic_pointer_cast<RemoteBlobTensor>(tensor._ptr)) {
@@ -4,10 +4,10 @@
<a name="fig1"></a>
```mermaid
classDiagram
classDiagram
direction LR
pooling --<| primitive_base
convolution --<| primitive_base
convolution --<| primitive_base
class primitive_base{<<PType>>}
primitive_base --<| primitive
primitive --o program_node
@@ -78,7 +78,7 @@ A more detailed description of each component is described in the sections below
## primitive
```cpp
struct primitive {
struct primitive {
...
const primitive_id id;
const primitive_type* type;
@@ -96,7 +96,7 @@ An example creation of a `arg_max_min` primitive:
cldnn::arg_max_min top_k_prim = cldnn::arg_max_min("top_k", { "input" }, arg_max_min::max, top_k, arg_max_min::y, arg_max_min::sort_by_values, false, "", padding(), data_types::f32);
```
In GPU plugin, the *primitives* are converted from ngraph [operations](https://github.com/openvinotoolkit/openvino/tree/master/src/plugins/intel_gpu/src/plugin/ops).
In GPU plugin, the *primitives* are converted from OpenVINO [operations](https://github.com/openvinotoolkit/openvino/tree/master/src/plugins/intel_gpu/src/plugin/ops).
## topology
```cpp
@@ -200,7 +200,7 @@ class primitive_inst {
std::vector<memory::cptr> _intermediates_memory;
event::ptr execute(const std::vector<event::ptr>& events);
memory::ptr allocate_output();
memory::ptr allocate_output();
...
};
```
+7 -23
View File
@@ -39,7 +39,7 @@ Behavior when both versions are specified is not defined.
Some options also allow multiple prefixes: `OV` and `OV_GPU`. `OV` prefix is intended to be used for options common for all OpenVINO components. When an option is set twice with different prefixes, then `OV_GPU` has higher priority.
### List of parameters
### List of parameters
This is a part of the full list. To get all parameters, see OV_GPU_Help result.
@@ -66,12 +66,12 @@ This is a part of the full list. To get all parameters, see OV_GPU_Help result.
The execution graph (also known as a runtime graph) is a device-specific graph after all transformations applied by the plugin. It is a very useful
feature for performance analysis and it allows finding a source of performance regressions quickly. The execution graph can be retrieved from the plugin
using `GetExecGraphInfo()` method of `InferenceEngine::ExecutableNetwork` and then serialized as usual IR:
using `get_runtime_model()` method of `ov::CompiledModel` and then serialized as usual IR:
```cpp
ExecutableNetwork exeNetwork;
ov::CompiledModel compiled_model;
// Load some model into the plugin
CNNNetwork execGraphInfo = exeNetwork.GetExecGraphInfo();
execGraphInfo.serialize("/path/to/serialized/exec/graph.xml");
std::shared_ptr<ov::Model> runtime_model = compiled_model.get_runtime_model();
ov::serialize(runtime_model, "/path/to/serialized/exec/graph.xml");
```
The capability to retrieve the execution graph and store it on the disk is integrated into `benchmark_app`. The execution graph can be simply dumped
@@ -116,14 +116,14 @@ Most of the data here is very handy for performance analysis. For example, for e
This graph can be visualized using Netron tool and all these properties can be analyzed there.
> **NOTE**: execution time collection for each primitive requires `CONFIG_KEY(PERF_COUNT)` to be enabled (`benchmark_app` does it automatically). Therefore, the overall model execution time is usually much worse in such use cases.
> **NOTE**: execution time collection for each primitive requires `ov::enable_profiling` to be enabled (`benchmark_app` does it automatically). Therefore, the overall model execution time is usually much worse in such use cases.
## Performance counters
This feature is a simplified version of the execution graph as it provides much less information, but it might be more suitable for quick analysis and some kind of
processing with scripts.
Performance counters can be retrieved from each `InferenceEngine::InferRequest` object using `getPerformanceCounts()` method. This feature is also integrated
Performance counters can be retrieved from each `ov::InferRequest` object using `get_profiling_info()` method. This feature is also integrated
into `benchmark_app` and the counters can be printed to count using `-pc` parameter.
The format looks as follows:
@@ -149,14 +149,6 @@ So it allows you to quickly check the execution time of some operation on the de
* You can dump graphs with `OV_GPU_DumpGraphs` of debug config. For the usage of debug config, see the [link](#debug-config).
* Alternatively, you can also enable the dumps from the application source code:
clDNN plugin has the special internal config option - `graph_dumps_dir`, which can be set from the user app via plugin config:
```cpp
Core ie;
std::map<std::string, std::string> device_config;
device_config[CLDNN_CONFIG_KEY(GRAPH_DUMPS_DIR)] = "/some/existing/path/";
ie.SetConfig(device_config, "GPU");
```
For each stage, it dumps:
```
@@ -175,14 +167,6 @@ Since *Intel_GPU* source tree contains only *templates* of the OpenCL™ kernels
* You can use `OV_GPU_DumpSources` of debug config. For the usage of debug config, see [link](#debug-config).
* You can also dump OpenCL source code by changing OpenVINO source code:
clDNN plugin has the special internal config option - `sources_dumps_dir`, which can be set from the user app via plugin config:
```cpp
Core ie;
std::map<std::string, std::string> device_config;
device_config[CLDNN_CONFIG_KEY(SOURCES_DUMPS_DIR)] = "/some/existing/path/";
ie.SetConfig(device_config, "GPU");
```
When this key is enabled, the plugin dumps multiple files with the following names:
```
@@ -3,69 +3,67 @@
The simplified workflow in the GPU plugin is shown in the diagram below (click it for higher resolution):
```mermaid
classDiagram
class `intel_gpu::Plugin` {Inference Engine plugin
implementation for GPU}
class `intel_gpu::CompiledModel` {Device specific network
representation that can be executed}
class `intel_gpu::InferRequestAsync` {
Inference request for specific executable network.
Wrapper for input and output memory}
class `intel_gpu::TransformationPipeline` {Set of ngraph-based transformations
configured by GPU plugin}
`Core::compile_model()` --> `intel_gpu::CompiledModel`
`CompiledModel::create_infer_request()` -->`intel_gpu::InferRequestAsync`
`InferRequest::start_async()` --> `intel_gpu::network`
`intel_gpu::Plugin` --|> `InferenceEngine::InferencePluginInternal`
classDiagram
%% Public API classes
class `ov::CompiledModel`
class `ov::InferRequest`
class `ov::Core`
%% Plugin API interface %%
class `ov::IPlugin`
class `ov::ICompiledModel`
class `ov::IAsyncInferRequest`
class `ov::ISyncInferRequest`
%% Plugin API Impl %%
class `intel_gpu::Plugin` { OpenVINO plugin implementation for GPU }
class `intel_gpu::CompiledModel`
class `intel_gpu::AsyncInferRequest` { Asynchronous version of infer request }
class `intel_gpu::SyncInferRequest` { Inference request for specific executable network. Wrapper for input and output memory }
`intel_gpu::Plugin` --|> `ov::IPlugin`
`intel_gpu::CompiledModel` --|> `ov::ICompiledModel`
`intel_gpu::SyncInferRequest` --|> `ov::ISyncInferRequest`
`intel_gpu::AsyncInferRequest` --|> `ov::IAsyncInferRequest`
`intel_gpu::Plugin` --> `intel_gpu::CompiledModel` : Create
`intel_gpu::CompiledModel` --|> `InferenceEngine::ExecutableNetworkThreadSafeDefault`
`intel_gpu::CompiledModel` --> `intel_gpu::InferRequestAsync` : Create
`intel_gpu::SyncInferRequest` "1" --* "1" `intel_gpu::AsyncInferRequest`
%% Plugin implementation details %%
class `intel_gpu::TransformationPipeline` {Set of ngraph-based transformations configured by GPU plugin }
class `intel_gpu::Graph` { Per stream copy of compiled graph with independent memory }
class `intel_gpu::ProgramBuilder` { Object for operations semantic translation and graph compilation }
`ov::Core` --> `intel_gpu::CompiledModel` : compile_model()
`ov::CompiledModel` -->`intel_gpu::AsyncInferRequest` : create_infer_request()
`ov::InferRequest` --> `intel_gpu::network` : start_async()
`intel_gpu::CompiledModel` --> `intel_gpu::AsyncInferRequest` : Create
`intel_gpu::TransformationPipeline` --> `ov::Model`
`intel_gpu::TransformationPipeline` --> `intel_gpu::CompiledModel`
`InferenceEngine::InferRequestInternal`
class `intel_gpu::Graph` {Per stream copy of
compiled graph with
independent memory}
`intel_gpu::Graph` "1..N" --* `intel_gpu::CompiledModel`
class `intel_gpu::ProgramBuilder` {Object for operations
semantic translation and
graph compilation}
`intel_gpu::CompiledModel` --> `intel_gpu::ProgramBuilder` : Create
`intel_gpu::ProgramBuilder` "1" --o "N" `intel_gpu::Graph`
class `intel_gpu::convolution` {convolution operation descriptor}
class `intel_gpu::data` {Primitive representing
constant data in a topology}
class `intel_gpu::data` {Primitive representing constant data in a topology }
class `intel_gpu::input_layout` {Represents dynamic input data}
class `intel_gpu::primitive_base` {<<Interface>>}
`intel_gpu::convolution` ..<| `intel_gpu::primitive_base`
`intel_gpu::data` ..<| `intel_gpu::primitive_base`
`intel_gpu::input_layout` ..<| `intel_gpu::primitive_base`
`Any other primitive` ..<| `intel_gpu::primitive_base`
class `intel_gpu::topology` {
Set of primitives. Each primitive
knows operation parameters,
it's inputs and outputs}
class `intel_gpu::program` {
Class that contains compiled topology.
All kernels are selected,
memory dependencies are resolved,
the only missing thing - memory for intermediate buffers}
class `intel_gpu::topology` { Set of primitives. Each primitive knows operation parameters, it's inputs and outputs }
class `intel_gpu::program` { Class that contains compiled topology. All kernels are selected, memory dependencies are resolved, the only missing thing - memory for intermediate buffers }
`intel_gpu::primitive_base` "0..N" --o `intel_gpu::topology`
`intel_gpu::program` --> `intel_gpu::topology`
`intel_gpu::ProgramBuilder` --> `intel_gpu::topology` : Create
`intel_gpu::ProgramBuilder` --> `intel_gpu::program` : Create
class `intel_gpu::program_node` {Base class for representation of a single graph node}
class `intel_gpu::primitive_impl` {
<<interface>>
Base class for representation of a single graph node}
class `intel_gpu::typed_primitive_onednn_impl` {Implementations that use oneDNN library}
class `oneDNN library` {statically linked into GPU plugin}
class `intel_gpu::typed_primitive_ocl_impl` {OCL implementations that use
kernels from kernel_selector}
class `intel_gpu::kernel_selector` {
module that stores OCL kernels
for primitives and has embed some
rules for optimal kernel selection}
class `intel_gpu::program_node` { Base class for representation of a single graph node }
class `intel_gpu::primitive_impl` { <<interface>> Base class for representation of a single graph node }
class `intel_gpu::typed_primitive_onednn_impl` {Implementations that use oneDNN library }
class `oneDNN library` { statically linked into GPU plugin }
class `intel_gpu::typed_primitive_ocl_impl` { OCL implementations that use kernels from kernel_selector }
class `intel_gpu::kernel_selector` { module that stores OCL kernels for primitives and has embed some rules for optimal kernel selection }
`intel_gpu::program_node` --o `intel_gpu::program`
`intel_gpu::primitive_impl` --o `intel_gpu::program_node`
`intel_gpu::typed_primitive_onednn_impl` ..<| `intel_gpu::primitive_impl`
@@ -73,26 +71,18 @@ rules for optimal kernel selection}
`intel_gpu::typed_primitive_ocl_impl` ..> `intel_gpu::kernel_selector`
`intel_gpu::typed_primitive_onednn_impl` --> `oneDNN bridge` : Use
`intel_gpu::typed_primitive_onednn_impl` ..> `oneDNN library`
class `intel_gpu::build_options` {Set of options for graph compilations}
class `intel_gpu::pass_manager` {Helper to run graph transformations}
class `intel_gpu::base_pass` {
<<Interface>>
Base class for graph transformations}
class `intel_gpu::build_options` { Set of options for graph compilations }
class `intel_gpu::pass_manager` { Helper to run graph transformations }
class `intel_gpu::base_pass` { <<Interface>> Base class for graph transformations}
`intel_gpu::program` --> `intel_gpu::build_options`
`intel_gpu::program` --> `intel_gpu::pass_manager` : Use
`intel_gpu::program` --> `intel_gpu::base_pass` : Use
`intel_gpu::pass_manager` --> `intel_gpu::base_pass` : Run
class `intel_gpu::prepare_primitive_fusing` {
Pass that fuses multiple operations into single node}
class `intel_gpu::prepare_quantization` {
Pass that prepares models for low precision execution}
class `intel_gpu::reorder_inputs` {
Pass that is responsible for layout/impl selection}
class `intel_gpu::compile_graph` {
Pass that selects and creates
best implementation for each primitive}
class `intel_gpu::remove_redundant_reorders` {
Pass that optimizes reorders in the graph}
class `intel_gpu::prepare_primitive_fusing` { Pass that fuses multiple operations into single node }
class `intel_gpu::prepare_quantization` { Pass that prepares models for low precision execution }
class `intel_gpu::reorder_inputs` { Pass that is responsible for layout/impl selection }
class `intel_gpu::compile_graph` { Pass that selects and creates best implementation for each primitive }
class `intel_gpu::remove_redundant_reorders` { Pass that optimizes reorders in the graph }
`intel_gpu::prepare_primitive_fusing`--|> `intel_gpu::base_pass`
`intel_gpu::prepare_quantization`--|> `intel_gpu::base_pass`
`intel_gpu::reorder_inputs`--|> `intel_gpu::base_pass`
@@ -100,31 +90,23 @@ Pass that optimizes reorders in the graph}
`intel_gpu::layout_optimizer`--|> `intel_gpu::base_pass`
`intel_gpu::remove_redundant_reorders`--|> `intel_gpu::base_pass`
`intel_gpu::reorder_inputs`--> `intel_gpu::layout_optimizer` : Use
class `intel_gpu::network` {
A program with allocated memory.
Can be executed on the device}
`intel_gpu::InferRequestAsync` --> `intel_gpu::network` : Set input/output memory and run execution
`intel_gpu::network` --> `intel_gpu::InferRequestAsync` : Return inference result
class `intel_gpu::tensor` {Size of memory buffer}
class `intel_gpu::format` {Order of elements in memory}
class `intel_gpu::data_type` {elements precision}
class `intel_gpu::memory_pool` {
Object that tracks memory allocations
and tries to reuse memory buffers}
class `intel_gpu::layout` {Memory descriptor}
class `intel_gpu::memory` {GPU memory object}
class `intel_gpu::stream` {
Abstraction for queue.
Knows how to submit kernels and
provide some synchronization capabilities}
class `intel_gpu::event` {Synchronization primitive}
class `intel_gpu::kernel` {Holds kernel handle}
class `intel_gpu::engine` {Engine for specific device,
responsible for memory allocations}
class `intel_gpu::device` {Holds context/device handles for selected backend}
class `intel_gpu::device_info` {Storage for device capabilities and info}
class `intel_gpu::engine_configuration` {Options for engine}
class `intel_gpu::device_query` {Detects available devices for given backend}
class `intel_gpu::network` { A program with allocated memory.Can be executed on the device }
`intel_gpu::AsyncInferRequest` --> `intel_gpu::network` : Set input/output memory and run execution
`intel_gpu::network` --> `intel_gpu::AsyncInferRequest` : Return inference result
class `intel_gpu::tensor` { Size of memory buffer }
class `intel_gpu::format` { Order of elements in memory }
class `intel_gpu::data_type` { elements precision }
class `intel_gpu::memory_pool` { Object that tracks memory allocations and tries to reuse memory buffers }
class `intel_gpu::layout` { Memory descriptor }
class `intel_gpu::memory` { GPU memory object }
class `intel_gpu::stream` { Abstraction for queue. Knows how to submit kernels and provide some synchronization }
class `intel_gpu::event` { Synchronization primitive }
class `intel_gpu::kernel` { Holds kernel handle }
class `intel_gpu::engine` { Engine for specific device, responsible for memory allocations }
class `intel_gpu::device` { Holds context/device handles for selected backend }
class `intel_gpu::device_info` { Storage for device capabilities and info }
class `intel_gpu::engine_configuration` { Options for engine }
class `intel_gpu::device_query` { Detects available devices for given backend }
`intel_gpu::tensor` --o `intel_gpu::layout`
`intel_gpu::format` --o `intel_gpu::layout`
`intel_gpu::data_type` --o `intel_gpu::layout`
@@ -142,8 +124,6 @@ class `intel_gpu::device_query` {Detects available devices for given backend}
`intel_gpu::device` --o `intel_gpu::engine`
`intel_gpu::device_info` --o `intel_gpu::device`
`intel_gpu::device_query` --> `intel_gpu::device`
`OCL Implementation of Runtime`..<| `Runtime module API & common`
`SYCL/L0 Implementation of Runtime (POC)`..<| `Runtime module API & common`
```
## See also
@@ -152,4 +132,4 @@ class `intel_gpu::device_query` {Detects available devices for given backend}
* [OpenVINO Core Components](../../../README.md)
* [OpenVINO Plugins](../../README.md)
* [OpenVINO GPU Plugin](../README.md)
* [Developer documentation](../../../../docs/dev/index.md)
* [Developer documentation](../../../../docs/dev/index.md)
@@ -244,7 +244,7 @@ public:
using variables_state_info_map = std::map<std::string, cldnn::layout>;
void set_variables_state_info(const std::string& variable_id, const cldnn::layout& layout);
const variables_state_info_map& get_variables_state_info() const;
const ExecutionConfig& get_config() const { return _config; }
ShapePredictor& get_shape_predictor() { return *_shape_predictor; }
@@ -6,43 +6,11 @@
#define RUN_ALL_MODEL_CACHING_TESTS
#include <vector>
#include <streambuf>
#include <unordered_map>
#include "openvino/core/deprecated.hpp"
#include "ie/ie_common.h"
namespace cldnn {
class serial_util {
public:
OPENVINO_SUPPRESS_DEPRECATED_START
static InferenceEngine::Layout layout_from_string(const std::string& name) {
static const std::unordered_map<std::string, InferenceEngine::Layout> layouts = {
{ "ANY", InferenceEngine::Layout::ANY },
{ "NCHW", InferenceEngine::Layout::NCHW },
{ "NHWC", InferenceEngine::Layout::NHWC },
{ "NCDHW", InferenceEngine::Layout::NCDHW },
{ "NDHWC", InferenceEngine::Layout::NDHWC },
{ "OIHW", InferenceEngine::Layout::OIHW },
{ "GOIHW", InferenceEngine::Layout::GOIHW },
{ "OIDHW", InferenceEngine::Layout::OIDHW },
{ "GOIDHW", InferenceEngine::Layout::GOIDHW },
{ "SCALAR", InferenceEngine::Layout::SCALAR },
{ "C", InferenceEngine::Layout::C },
{ "CHW", InferenceEngine::Layout::CHW },
{ "HWC", InferenceEngine::Layout::HWC },
{ "HW", InferenceEngine::Layout::HW },
{ "NC", InferenceEngine::Layout::NC },
{ "CN", InferenceEngine::Layout::CN },
{ "BLOCKED", InferenceEngine::Layout::BLOCKED }
};
auto it = layouts.find(name);
if (it != layouts.end()) {
return it->second;
}
OPENVINO_THROW("Unknown layout with name '", name, "'");
}
OPENVINO_SUPPRESS_DEPRECATED_END
};
class membuf : public std::streambuf {
public:
membuf() : _pos(0) { }
@@ -4,29 +4,29 @@
#pragma once
#include "openvino/runtime/iasync_infer_request.hpp"
#include "intel_gpu/plugin/sync_infer_request.hpp"
#include <string>
#include <map>
#include <cpp_interfaces/impl/ie_infer_async_request_thread_safe_default.hpp>
#include "intel_gpu/plugin/infer_request.hpp"
namespace ov {
namespace intel_gpu {
class AsyncInferRequest : public InferenceEngine::AsyncInferRequestThreadSafeDefault {
class AsyncInferRequest : public ov::IAsyncInferRequest {
public:
using Parent = InferenceEngine::AsyncInferRequestThreadSafeDefault;
AsyncInferRequest(const InferRequest::Ptr &inferRequest,
const InferenceEngine::ITaskExecutor::Ptr& taskExecutor,
const InferenceEngine::ITaskExecutor::Ptr& waitExecutor,
const InferenceEngine::ITaskExecutor::Ptr& callbackExecutor);
using Parent = ov::IAsyncInferRequest;
AsyncInferRequest(const std::shared_ptr<SyncInferRequest>& infer_request,
const std::shared_ptr<ov::threading::ITaskExecutor>& task_executor,
const std::shared_ptr<ov::threading::ITaskExecutor>& wait_executor,
const std::shared_ptr<ov::threading::ITaskExecutor>& callback_executor);
~AsyncInferRequest();
~AsyncInferRequest() override;
void StartAsync_ThreadUnsafe() override;
void start_async() override;
private:
InferRequest::Ptr _inferRequest;
InferenceEngine::ITaskExecutor::Ptr _waitExecutor;
std::shared_ptr<SyncInferRequest> m_infer_request;
std::shared_ptr<ov::threading::ITaskExecutor> m_wait_executor;
};
} // namespace intel_gpu
@@ -1,33 +0,0 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include <map>
#include <cpp_interfaces/impl/ie_infer_async_request_thread_safe_default.hpp>
#include "intel_gpu/plugin/infer_request_legacy.hpp"
namespace ov {
namespace intel_gpu {
class AsyncInferRequestLegacy : public InferenceEngine::AsyncInferRequestThreadSafeDefault {
public:
using Parent = InferenceEngine::AsyncInferRequestThreadSafeDefault;
AsyncInferRequestLegacy(const InferRequestLegacy::Ptr &inferRequest,
const InferenceEngine::ITaskExecutor::Ptr& taskExecutor,
const InferenceEngine::ITaskExecutor::Ptr& waitExecutor,
const InferenceEngine::ITaskExecutor::Ptr& callbackExecutor);
~AsyncInferRequestLegacy();
void StartAsync_ThreadUnsafe() override;
private:
InferRequestLegacy::Ptr _inferRequest;
InferenceEngine::ITaskExecutor::Ptr _waitExecutor;
};
} // namespace intel_gpu
} // namespace ov
@@ -4,16 +4,26 @@
#pragma once
#include <ie_layouts.h>
#include <ostream>
#include "intel_gpu/runtime/layout.hpp"
#include "openvino/core/layout.hpp"
#include "openvino/core/deprecated.hpp"
#include "ngraph/type/element_type.hpp"
#include "openvino/core/type/element_type.hpp"
namespace ov {
namespace intel_gpu {
enum class TensorType {
BT_EMPTY,
BT_BUF_INTERNAL,
BT_BUF_SHARED,
BT_USM_SHARED,
BT_USM_HOST_INTERNAL,
BT_USM_DEVICE_INTERNAL,
BT_IMG_SHARED,
BT_SURF_SHARED,
BT_DX_BUF_SHARED,
};
#define TensorValue(val) static_cast<cldnn::tensor::value_type>(val)
inline cldnn::tensor tensor_from_dims(const ov::Shape& dims, int def = 1) {
@@ -29,121 +39,25 @@ inline cldnn::tensor tensor_from_dims(const ov::Shape& dims, int def = 1) {
}
}
OPENVINO_SUPPRESS_DEPRECATED_START
inline cldnn::data_types DataTypeFromPrecision(InferenceEngine::Precision p) {
switch (p) {
case InferenceEngine::Precision::I16:
case InferenceEngine::Precision::U16:
case InferenceEngine::Precision::FP32:
case InferenceEngine::Precision::FP64:
return cldnn::data_types::f32;
case InferenceEngine::Precision::FP16:
return cldnn::data_types::f16;
case InferenceEngine::Precision::U8:
return cldnn::data_types::u8;
case InferenceEngine::Precision::I8:
return cldnn::data_types::i8;
case InferenceEngine::Precision::I32:
case InferenceEngine::Precision::U32:
case InferenceEngine::Precision::U64:
return cldnn::data_types::i32;
case InferenceEngine::Precision::I64:
return cldnn::data_types::i64;
case InferenceEngine::Precision::BIN:
return cldnn::data_types::bin;
case InferenceEngine::Precision::BOOL:
return cldnn::data_types::i8;
default:
IE_THROW(ParameterMismatch)
<< "The plugin does not support " << p.name() << " precision";
}
inline cldnn::layout make_layout(const ov::element::Type type, const ov::Shape& shape) {
return cldnn::layout{ov::PartialShape{shape},
cldnn::element_type_to_data_type(type),
cldnn::format::get_default_format(shape.size())};
}
inline InferenceEngine::Precision PrecisionFromDataType(cldnn::data_types dt) {
switch (dt) {
case cldnn::data_types::bin:
return InferenceEngine::Precision::ePrecision::BIN;
case cldnn::data_types::u8:
return InferenceEngine::Precision::ePrecision::U8;
case cldnn::data_types::i8:
return InferenceEngine::Precision::ePrecision::I8;
case cldnn::data_types::f16:
return InferenceEngine::Precision::ePrecision::FP16;
case cldnn::data_types::f32:
return InferenceEngine::Precision::ePrecision::FP32;
case cldnn::data_types::i32:
return InferenceEngine::Precision::ePrecision::I32;
case cldnn::data_types::i64:
return InferenceEngine::Precision::ePrecision::I64;
default:
OPENVINO_THROW("The plugin does not support ", cldnn::data_type_traits::name(dt), " data type");
inline ov::element::Type convert_to_supported_device_type(ov::element::Type et) {
switch (et) {
case ov::element::f64:
case ov::element::i16:
case ov::element::u16:
return ov::element::f32;
case ov::element::u64:
case ov::element::u32:
return ov::element::i32;
default: return et;
}
}
inline cldnn::format FormatFromLayout(InferenceEngine::Layout l) {
switch (l) {
// TODO: change 6d case once new layout added in IE
case InferenceEngine::Layout::BLOCKED:
return cldnn::format::bfwzyx;
case InferenceEngine::Layout::NCDHW:
return cldnn::format::bfzyx;
case InferenceEngine::Layout::NCHW:
case InferenceEngine::Layout::NC:
case InferenceEngine::Layout::CHW:
case InferenceEngine::Layout::C:
case InferenceEngine::Layout::SCALAR:
return cldnn::format::bfyx;
case InferenceEngine::Layout::NHWC:
return cldnn::format::byxf;
default:
IE_THROW(ParameterMismatch) << "The plugin does not support " << l << " layout";
}
}
inline cldnn::format FormatFromTensorDesc(InferenceEngine::TensorDesc desc) {
switch (desc.getLayout()) {
case InferenceEngine::Layout::BLOCKED: {
if (desc.getDims().size() == 6)
return cldnn::format::bfwzyx;
else if (desc.getDims().size() == 5)
return cldnn::format::bfzyx;
else if (desc.getDims().size() <= 4)
return cldnn::format::bfyx;
}
case InferenceEngine::Layout::NCDHW:
return cldnn::format::bfzyx;
case InferenceEngine::Layout::NCHW:
case InferenceEngine::Layout::NC:
case InferenceEngine::Layout::CHW:
case InferenceEngine::Layout::C:
case InferenceEngine::Layout::SCALAR:
return cldnn::format::bfyx;
case InferenceEngine::Layout::NHWC:
return cldnn::format::byxf;
default:
IE_THROW(ParameterMismatch)
<< "The plugin does not support " << desc.getLayout() << " layout";
}
}
inline cldnn::format ImageFormatFromLayout(InferenceEngine::Layout l) {
switch (l) {
// currently, nv12 is the only supported image layout
case InferenceEngine::Layout::BLOCKED:
case InferenceEngine::Layout::NCDHW:
case InferenceEngine::Layout::NCHW:
case InferenceEngine::Layout::NC:
case InferenceEngine::Layout::CHW:
case InferenceEngine::Layout::C:
case InferenceEngine::Layout::NHWC:
return cldnn::format::nv12;
default:
IE_THROW(ParameterMismatch)
<< "The plugin does not support " << l << " image layout";
}
}
OPENVINO_SUPPRESS_DEPRECATED_END
/// WA: Force exit. Any opencl api call can be hang after CL_OUT_OF_RESOURCES.
inline void ForceExit() {
std::cerr << "[GPU] force exit.\n"
@@ -156,4 +70,11 @@ inline void ForceExit() {
}
} // namespace intel_gpu
inline std::ostream& operator<<(std::ostream& os, const ov::AnyMap& params) {
for (const auto& p : params) {
os << p.first << " : " << p.second.as<std::string>() << std::endl;
}
return os;
}
} // namespace ov
@@ -4,51 +4,70 @@
#pragma once
#include "openvino/runtime/icompiled_model.hpp"
#include "intel_gpu/plugin/graph.hpp"
#include "intel_gpu/plugin/plugin.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/runtime/execution_config.hpp"
#include <vector>
#include <map>
#include <set>
#include <memory>
#include <string>
#include <utility>
#include "ie_blob.h"
#include "cpp/ie_cnn_network.h"
#include <cpp_interfaces/impl/ie_executable_network_thread_safe_default.hpp>
#include "intel_gpu/plugin/graph.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/runtime/execution_config.hpp"
namespace ov {
namespace intel_gpu {
class CompiledModel : public InferenceEngine::ExecutableNetworkThreadSafeDefault {
class CompiledModel : public ov::ICompiledModel {
public:
typedef std::shared_ptr<CompiledModel> Ptr;
using Ptr = std::shared_ptr<CompiledModel>;
CompiledModel(InferenceEngine::CNNNetwork &network, InferenceEngine::RemoteContext::Ptr context, const ExecutionConfig& config,
InferenceEngine::InputsDataMap* inputs = nullptr, InferenceEngine::OutputsDataMap* outputs = nullptr);
CompiledModel(cldnn::BinaryInputBuffer& ib, InferenceEngine::RemoteContext::Ptr context, const ExecutionConfig& config,
InferenceEngine::InputsDataMap* inputs = nullptr, InferenceEngine::OutputsDataMap* outputs = nullptr);
CompiledModel(std::shared_ptr<ov::Model> model,
const std::shared_ptr<const ov::IPlugin>& plugin,
RemoteContextImpl::Ptr context,
const ExecutionConfig& config);
CompiledModel(cldnn::BinaryInputBuffer ib,
const std::shared_ptr<const ov::IPlugin>& plugin,
RemoteContextImpl::Ptr context,
const ExecutionConfig& config);
void Export(std::ostream& networkModel) override;
std::shared_ptr<ngraph::Function> GetExecGraphInfo() override;
InferenceEngine::IInferRequestInternal::Ptr CreateInferRequest() override;
InferenceEngine::IInferRequestInternal::Ptr CreateInferRequestImpl(InferenceEngine::InputsDataMap networkInputs,
InferenceEngine::OutputsDataMap networkOutputs) override;
InferenceEngine::IInferRequestInternal::Ptr CreateInferRequestImpl(const std::vector<std::shared_ptr<const ov::Node>>& inputs,
const std::vector<std::shared_ptr<const ov::Node>>& outputs) override;
template <class T>
InferenceEngine::IInferRequestInternal::Ptr GetInferRequestImpl(const std::vector<std::shared_ptr<const ov::Node>>& inputs,
const std::vector<std::shared_ptr<const ov::Node>>& outputs);
InferenceEngine::Parameter GetMetric(const std::string &name) const override;
InferenceEngine::Parameter GetConfig(const std::string &name) const override;
std::shared_ptr<InferenceEngine::RemoteContext> GetContext() const override;
std::shared_ptr<ov::IAsyncInferRequest> create_infer_request() const override;
std::shared_ptr<ov::ISyncInferRequest> create_sync_infer_request() const override;
std::vector<std::shared_ptr<Graph>> m_graphs;
InferenceEngine::RemoteContext::Ptr m_context;
void export_model(std::ostream& model) const override;
std::shared_ptr<const ov::Model> get_runtime_model() const override;
ov::Any get_property(const std::string& name) const override;
void set_property(const ov::AnyMap& properties) override {
OPENVINO_ASSERT_HELPER(::ov::NotImplemented,
"",
false,
"Not Implemented: ",
"CompiledModel::set_property is not supported by this plugin!");
};
const std::vector<ov::Output<const ov::Node>>& outputs() const override { return m_outputs; }
const std::vector<ov::Output<const ov::Node>>& inputs() const override { return m_inputs;}
bool is_new_api() const { return std::static_pointer_cast<const ov::intel_gpu::Plugin>(get_plugin())->is_new_api(); }
RemoteContextImpl::Ptr get_context_impl() const {return m_context; }
const std::vector<std::shared_ptr<Graph>>& get_graphs() const;
std::shared_ptr<Graph> get_graph(size_t n) const;
private:
RemoteContextImpl::Ptr m_context;
ExecutionConfig m_config;
InferenceEngine::ITaskExecutor::Ptr m_taskExecutor;
InferenceEngine::ITaskExecutor::Ptr m_waitExecutor;
InferenceEngine::CNNNetwork m_network;
std::shared_ptr<ov::threading::ITaskExecutor> m_wait_executor;
std::shared_ptr<ov::Model> m_model;
std::string m_model_name;
std::vector<ov::Output<const ov::Node>> m_inputs;
std::vector<ov::Output<const ov::Node>> m_outputs;
std::vector<std::shared_ptr<Graph>> m_graphs;
bool m_loaded_from_cache;
};
} // namespace intel_gpu
@@ -8,6 +8,12 @@
# define NOMINMAX
#endif
#include "intel_gpu/graph/network.hpp"
#include "intel_gpu/graph/topology.hpp"
#include "intel_gpu/plugin/custom_layer.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/program_builder.hpp"
#include <vector>
#include <map>
#include <set>
@@ -15,74 +21,48 @@
#include <string>
#include <utility>
#include <vector>
#include "ie_blob.h"
#include "cpp/ie_cnn_network.h"
#include "intel_gpu/graph/network.hpp"
#include "intel_gpu/graph/topology.hpp"
#include <cpp_interfaces/impl/ie_executable_network_thread_safe_default.hpp>
#include "intel_gpu/plugin/custom_layer.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/remote_blob.hpp"
#include "intel_gpu/plugin/program_builder.hpp"
#include <condition_variable>
namespace ov {
namespace intel_gpu {
class Graph {
class Graph final {
public:
using Ptr = std::shared_ptr<Graph>;
enum class Stage : uint32_t {
PREPROC = 1,
EXECUTE = 2,
POSTPROC = 4
};
typedef std::shared_ptr<Graph> Ptr;
using variable_states_map = std::map<std::string, std::vector<cldnn::network::VariableState::Ptr>>;
Graph(InferenceEngine::CNNNetwork& network,
const RemoteContextImpl::Ptr& context,
const ExecutionConfig& config,
uint16_t stream_id = 0,
InferenceEngine::InputsDataMap* inputs = nullptr,
InferenceEngine::OutputsDataMap* outputs = nullptr);
Graph(cldnn::BinaryInputBuffer& ib,
const RemoteContextImpl::Ptr& context,
const ExecutionConfig& config,
uint16_t stream_id = 0,
InferenceEngine::InputsDataMap* inputs = nullptr,
InferenceEngine::OutputsDataMap* outputs = nullptr);
explicit Graph(std::shared_ptr<Graph> graph, uint16_t stream_id = 0);
void Export(cldnn::BinaryOutputBuffer &ob);
std::shared_ptr<ngraph::Function> GetExecGraphInfo();
Graph(std::shared_ptr<ov::Model> model, const RemoteContextImpl::Ptr& context, const ExecutionConfig& config, uint16_t stream_id = 0);
Graph(cldnn::BinaryInputBuffer& ib, const RemoteContextImpl::Ptr& context, const ExecutionConfig& config, uint16_t stream_id = 0);
Graph(std::shared_ptr<Graph> graph, uint16_t stream_id = 0);
bool IsLoaded() const;
void export_model(cldnn::BinaryOutputBuffer &ob);
std::shared_ptr<ov::Model> get_runtime_model();
std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> GetPerformanceCounts() const;
void UpdatePerfStatistics();
bool is_loaded() const;
std::vector<ov::ProfilingInfo> get_profiling_info() const;
void update_profiling_info();
cldnn::engine& get_engine() const { return m_context->get_engine(); }
const ExecutionConfig& get_config() const { return m_config; }
size_t GetMaxDynamicBatchSize() const { return m_config.get_property(ov::intel_gpu::max_dynamic_batch);}
const std::map<std::string, cldnn::layout>& GetInputLayouts() const { return m_program->GetInputLayouts(); }
const InferenceEngine::InputsDataMap GetNetworkInputs() const { return m_program->GetNetworkInputs(); }
const InferenceEngine::OutputsDataMap GetNetworkOutputs() const { return m_program->GetNetworkOutputs(); }
variable_states_map AllocateVariablesMemories();
std::map<std::string, std::pair<int64_t, int64_t>> GetInputDynBatchDims() { return m_program->m_input_batch_dim; }
std::map<std::string, int64_t> GetOutputDynBatchDims() { return m_program->m_output_batch_dim; }
size_t GetNetworksCount() const { return m_networks.size(); }
std::shared_ptr<cldnn::network> GetNetwork(size_t idx = 0) const;
InferenceEngine::SizeVector GetOutputSize(std::string outName) const;
std::string MapOutputName(std::string outName) const;
std::string getName() const { return m_networkName; }
const std::map<std::string, cldnn::layout>& get_input_layouts() const { return m_input_layouts; }
std::shared_ptr<cldnn::network> get_network() const;
std::string out_name_to_internal(std::string out_port_name) const;
void wait(Stage stage_mask) {
std::unique_lock<std::mutex> lock(m_infer_mutex);
m_cv.wait(lock, [&] {
m_cv.wait(lock, [&stage_mask, this] {
return (m_state & (uint32_t)stage_mask) == 0;
});
m_state |= (uint32_t)stage_mask;
}
void notify(Stage stage_mask) {
{
std::lock_guard<std::mutex> lock(m_infer_mutex);
@@ -94,30 +74,25 @@ public:
bool use_external_queue() const;
protected:
private:
RemoteContextImpl::Ptr m_context;
std::shared_ptr<ProgramBuilder> m_program;
std::string m_networkName;
ExecutionConfig m_config;
uint16_t m_stream_id;
uint32_t m_state;
uint32_t m_state = 0;
std::condition_variable m_cv;
std::mutex m_infer_mutex;
std::vector<std::shared_ptr<cldnn::network>> m_networks;
std::shared_ptr<cldnn::network> m_network;
std::map<std::string, cldnn::primitive_id> primitiveIDs;
std::map<std::string, std::vector<cldnn::primitive_id>> prevPrimitiveIDs;
std::map<cldnn::primitive_id, std::pair<std::string, PerfCounter>> perfMap;
std::vector<cldnn::primitive_id> profilingIDs;
std::map<std::string, InferenceEngine::SizeVector> outputDims;
std::map<std::string, cldnn::layout> m_input_layouts;
std::shared_ptr<cldnn::network> BuildNetwork(std::shared_ptr<cldnn::program> program);
void Build();
void UpdateLayersMaps();
std::shared_ptr<ngraph::Function> GetExecGraphInfoByPrimitivesInfo(std::vector<cldnn::primitive_info>& pi,
bool filter_const_primitives = true);
void build(std::shared_ptr<cldnn::program> program);
std::shared_ptr<ov::Model> get_runtime_model(std::vector<cldnn::primitive_info>& pi, bool filter_const_primitives = true);
};
} // namespace intel_gpu
@@ -1,106 +0,0 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <atomic>
#include "intel_gpu/plugin/graph.hpp"
#include <threading/ie_istreams_executor.hpp>
namespace ov {
namespace intel_gpu {
class CompiledModel;
class InferRequest : public InferenceEngine::IInferRequestInternal {
public:
using Ptr = std::shared_ptr<InferRequest>;
// make sure all blobs and cldnn::memory objects
// are in place and valid
void checkBlobs() override;
void InferImpl() override;
std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> GetPerformanceCounts() const override;
InferRequest(InferenceEngine::InputsDataMap networkInputs, InferenceEngine::OutputsDataMap networkOutputs,
const std::shared_ptr<CompiledModel>& execNetwork);
InferRequest(const std::vector<std::shared_ptr<const ov::Node>>& inputs,
const std::vector<std::shared_ptr<const ov::Node>>& outputs,
const std::shared_ptr<CompiledModel>& execNetwork);
InferRequest(const InferRequest &) = delete;
virtual ~InferRequest() = default;
InferenceEngine::Blob::Ptr GetBlob(const std::string& name) override;
void SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr &data) override;
void SetBlobs(const std::string& name, const std::vector<InferenceEngine::Blob::Ptr> &data) override;
std::vector<std::shared_ptr<InferenceEngine::IVariableStateInternal>> QueryState() override;
void SetGraph(std::shared_ptr<Graph> graph);
void EnableProfiling() { m_useProfiling = true; }
void EnableStreams() { m_useStreams = true; }
void setup_stream_graph();
void enqueue_notify();
void wait_notify();
void enqueue();
void wait();
bool use_external_queue() const { return m_useExternalQueue; }
void enable_external_queue() { m_useExternalQueue = true; }
private:
// This blob is used for outputs processing if output data type convertion or padding handling is needed
InferenceEngine::Blob::Ptr intermediate_output_blob = nullptr;
InferenceEngine::BlobMap users_blobs_matching;
InferenceEngine::BlobMap _deviceOutputs;
std::map<std::string, cldnn::primitive_id> inputsMap;
std::map<std::string, cldnn::primitive_id> outputsMap;
std::map<std::string, std::vector<InferenceEngine::Blob::Ptr>> inputTensorsMap;
bool m_useProfiling = false;
bool m_useStreams = false;
bool m_useExternalQueue = false;
std::shared_ptr<Graph> m_graph;
InferenceEngine::gpu::ClContext::Ptr m_context = nullptr;
InferenceEngine::IStreamsExecutor* streamExecutor = nullptr;
void prepare_input(const cldnn::primitive_id &inputName, InferenceEngine::Blob::Ptr &inputBlob,
std::vector<cldnn::event::ptr>& dependencies);
void prepare_output(const cldnn::primitive_id& outputName, InferenceEngine::Blob::Ptr& outputBlob,
std::vector<cldnn::event::ptr>& dependencies);
void allocate_dev_mem_if_needed(InferenceEngine::BlobMap& device_mems, InferenceEngine::Blob::Ptr& user_blob,
const cldnn::primitive_id& blob_name, const cldnn::layout& layout,
const bool need_lockable_mem = false);
InferenceEngine::Blob::Ptr create_host_blob(const InferenceEngine::TensorDesc& desc, bool is_dynamic);
InferenceEngine::Blob::Ptr create_device_blob(const InferenceEngine::TensorDesc& desc);
void copy_output_data(cldnn::memory::ptr outputMemory, InferenceEngine::Blob::Ptr bptr, std::vector<cldnn::event::ptr>& events);
template<typename RemoteBlobType, typename = typename std::enable_if<std::is_same<RemoteBlobType, RemoteCLbuffer>::value ||
std::is_same<RemoteBlobType, RemoteUSMbuffer>::value>::type>
InferenceEngine::Blob::Ptr create_remote_blob(const InferenceEngine::TensorDesc& desc, const cldnn::layout& layout,
const BlobType mem_type, void* mem_ptr = nullptr);
InferenceEngine::Blob::Ptr create_shared_device_blob(const InferenceEngine::TensorDesc& desc, const cldnn::layout& layout, void* usm_host_mem);
void allocate_inputs();
void allocate_outputs();
void set_input(const std::string& name, const InferenceEngine::Blob::Ptr& data);
void set_output(const std::string& name, const InferenceEngine::Blob::Ptr& data);
InferenceEngine::Blob::Ptr reinterpret_device_blob(InferenceEngine::Blob::Ptr data, const InferenceEngine::TensorDesc& new_desc);
std::map<cldnn::primitive_id, cldnn::network_output> internal_outputs;
};
} // namespace intel_gpu
} // namespace ov
@@ -1,115 +0,0 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <atomic>
#include "intel_gpu/plugin/graph.hpp"
#include <threading/ie_istreams_executor.hpp>
namespace ov {
namespace intel_gpu {
struct buf_info {
size_t buf_offset;
size_t buf_size;
};
class CompiledModel;
class InferRequestLegacy : public InferenceEngine::IInferRequestInternal {
public:
using Ptr = std::shared_ptr<InferRequestLegacy>;
// make sure all blobs and cldnn::memory objects
// are in place and valid
void checkBlobs() override;
void InferImpl() override;
std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> GetPerformanceCounts() const override;
InferRequestLegacy(InferenceEngine::InputsDataMap networkInputs, InferenceEngine::OutputsDataMap networkOutputs,
const std::shared_ptr<CompiledModel>& execNetwork);
InferRequestLegacy(const std::vector<std::shared_ptr<const ov::Node>>& inputs,
const std::vector<std::shared_ptr<const ov::Node>>& outputs,
const std::shared_ptr<CompiledModel>& execNetwork);
InferRequestLegacy(const InferRequestLegacy &) = delete;
virtual ~InferRequestLegacy() = default;
InferenceEngine::Blob::Ptr GetBlob(const std::string& name) override;
void SetBlob(const std::string& name, const InferenceEngine::Blob::Ptr &data) override;
void SetBlobs(const std::string& name, const std::vector<InferenceEngine::Blob::Ptr> &data) override;
void SetBatch(int batch = -1);
std::vector<std::shared_ptr<InferenceEngine::IVariableStateInternal>> QueryState() override;
void SetGraph(std::shared_ptr<Graph> graph);
void EnableProfiling() { m_useProfiling = true; }
void EnableStreams() { m_useStreams = true; }
void setup_stream_graph();
void preprocess_notify();
void enqueue_notify();
void wait_notify();
void preprocess();
void enqueue();
void wait();
void preprocess_dynamic();
void enqueue_dynamic();
void wait_dynamic();
bool use_external_queue() const { return m_useExternalQueue; }
void enable_external_queue() { m_useExternalQueue = true; }
private:
InferenceEngine::BlobMap _deviceOutputs;
std::map<std::string, cldnn::primitive_id> inputsMap;
std::map<std::string, cldnn::primitive_id> outputsMap;
std::map<std::string, std::vector<InferenceEngine::Blob::Ptr>> inputTensorsMap;
bool m_useProfiling = false;
bool m_useStreams = false;
bool m_useExternalQueue = false;
std::shared_ptr<Graph> m_graph;
InferenceEngine::gpu::ClContext::Ptr m_context = nullptr;
// dynamic batch stuff
std::map<std::string, std::vector<buf_info>> batchInputs;
std::map<std::string, std::vector<buf_info>> batchOutputs;
InferenceEngine::IStreamsExecutor* streamExecutor = nullptr;
void prepare_input(const cldnn::primitive_id &inputName, InferenceEngine::Blob::Ptr &inputBlob,
std::vector<cldnn::event::ptr>& dependencies);
void prepare_output(const cldnn::primitive_id& outputName, InferenceEngine::Blob::Ptr& outputBlob);
InferenceEngine::Blob::Ptr create_host_blob(const InferenceEngine::TensorDesc& desc,
std::shared_ptr<InferenceEngine::IAllocator> alloc = nullptr);
InferenceEngine::Blob::Ptr create_device_blob(const InferenceEngine::TensorDesc& desc, const cldnn::layout& layout);
void copy_output_data(cldnn::memory::ptr outputMemory, InferenceEngine::Blob::Ptr bptr, buf_info* bi = nullptr);
void copy_input_data(std::shared_ptr<cldnn::network> network, const cldnn::primitive_id &inputName,
const cldnn::layout& inputLayout, const InferenceEngine::Blob &inputBlob,
buf_info* bi = nullptr);
InferenceEngine::Blob::Ptr create_shared_device_blob(const InferenceEngine::TensorDesc& desc, const cldnn::layout& layout, void* usm_host_mem);
void allocate_inputs();
void allocate_outputs();
void allocate_inputs_dynamic();
void allocate_outputs_dynamic();
std::map<cldnn::primitive_id, cldnn::network_output> internal_outputs;
std::vector<std::map<cldnn::primitive_id, cldnn::network_output>> internal_outputs_dynamic;
Graph::variable_states_map variables_states_;
int m_curBatch = -1;
};
} // namespace intel_gpu
} // namespace ov
@@ -4,7 +4,6 @@
#include "intel_gpu/runtime/execution_config.hpp"
#include "ie_metric_helpers.hpp"
#include <ie_ngraph_utils.hpp>
#include "ie_plugin_config.hpp"
#include "gpu/gpu_config.hpp"
#include "cpp_interfaces/interface/ie_internal_plugin_config.hpp"
@@ -0,0 +1,145 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "intel_gpu/plugin/remote_tensor.hpp"
#include <remote_utils.hpp>
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifdef _WIN32
# include <gpu/gpu_context_api_dx.hpp>
#else
# include <gpu/gpu_context_api_va.hpp>
#endif
#include <string>
#include <map>
#include <memory>
namespace ov {
namespace intel_gpu {
class RemoteAllocator : public InferenceEngine::IAllocator {
protected:
friend class RemoteTensorImpl;
RemoteTensorImpl* m_tensor = nullptr;
mutable std::mutex locked_mutex;
mutable size_t locked_counter = 0;
mutable std::unique_ptr<cldnn::mem_lock<uint8_t>> locked_holder = nullptr;
mutable void* _handle = nullptr;
public:
using Ptr = std::shared_ptr<RemoteAllocator>;
RemoteAllocator(RemoteTensorImpl* tensor) : m_tensor(tensor) { }
/**
* @brief Maps handle to heap memory accessible by any memory manipulation routines.
* @return Generic pointer to memory
*/
void* lock(void* handle, InferenceEngine::LockOp = InferenceEngine::LOCK_FOR_WRITE) noexcept override {
try {
std::lock_guard<std::mutex> locker(locked_mutex);
if (locked_counter == 0) {
auto mem = m_tensor->get_original_memory();
auto& stream = mem->get_engine()->get_service_stream();
locked_holder = std::unique_ptr<cldnn::mem_lock<uint8_t>>(new cldnn::mem_lock<uint8_t>(mem, stream));
_handle = reinterpret_cast<void*>(locked_holder->data());
}
locked_counter++;
return _handle;
} catch (std::exception&) {
return nullptr;
}
};
/**
* @brief Unmaps memory by handle with multiple sequential mappings of the same handle.
* The multiple sequential mappings of the same handle are suppose to get the same
* result while there isn't a ref counter supported.
*/
void unlock(void* handle) noexcept override {
std::lock_guard<std::mutex> locker(locked_mutex);
locked_counter--;
if (locked_counter == 0)
locked_holder.reset();
}
/**
* @brief Allocates memory
* @param size The size in bytes to allocate
* @return Handle to the allocated resource
*/
void* alloc(size_t size) noexcept override { return nullptr; }
/**
* @brief Releases handle and all associated memory resources which invalidates the handle.
* @return false if handle cannot be released, otherwise - true.
*/
bool free(void* handle) noexcept override { return true; }
};
template<typename TpublicAPI>
class TypedRemoteBlob : public TpublicAPI, public ov::legacy_convert::TensorHolder {
public:
using Ptr = std::shared_ptr<TypedRemoteBlob>;
explicit TypedRemoteBlob(std::shared_ptr<RemoteTensorImpl> impl, InferenceEngine::gpu::ClContext::Ptr context)
: TpublicAPI(InferenceEngine::TensorDesc(InferenceEngine::details::convertPrecision(impl->get_element_type()),
impl->get_shape(),
InferenceEngine::TensorDesc::getLayoutByDims(impl->get_shape())))
, ov::legacy_convert::TensorHolder({impl, nullptr})
, m_impl(impl)
, m_context(context)
, m_allocator(std::make_shared<RemoteAllocator>(impl.get())) { }
void allocate() noexcept override { }
bool deallocate() noexcept override { return true; }
InferenceEngine::ParamMap getParams() const override { return m_impl->get_properties(); }
std::string getDeviceName() const noexcept override { return m_impl->get_device_name(); }
std::shared_ptr<InferenceEngine::RemoteContext> getContext() const noexcept override { return m_context; }
InferenceEngine::LockedMemory<void> buffer() noexcept override {
return InferenceEngine::LockedMemory<void>(m_allocator.get(), m_impl.get(), 0);
}
InferenceEngine::LockedMemory<const void> cbuffer() const noexcept override {
return InferenceEngine::LockedMemory<const void>(m_allocator.get(), m_impl.get(), 0);
}
InferenceEngine::LockedMemory<void> rwmap() noexcept override {
return InferenceEngine::LockedMemory<void>(m_allocator.get(), m_impl.get(), 0);
}
InferenceEngine::LockedMemory<const void> rmap() const noexcept override {
return InferenceEngine::LockedMemory<const void>(m_allocator.get(), m_impl.get(), 0);
}
InferenceEngine::LockedMemory<void> wmap() noexcept override {
return InferenceEngine::LockedMemory<void>(m_allocator.get(), m_impl.get(), 0);
}
void setShape(const InferenceEngine::SizeVector& dims) override { m_impl->set_shape(dims); }
private:
const std::shared_ptr<InferenceEngine::IAllocator> &getAllocator() const noexcept override { return m_allocator; }
void *getHandle() const noexcept override { return m_handle; }
std::shared_ptr<RemoteTensorImpl> m_impl;
std::shared_ptr<InferenceEngine::gpu::ClContext> m_context;
void* m_handle = nullptr;
std::shared_ptr<InferenceEngine::IAllocator> m_allocator;
};
using RemoteCLbuffer = TypedRemoteBlob<InferenceEngine::gpu::ClBufferBlob>;
using RemoteUSMbuffer = TypedRemoteBlob<InferenceEngine::gpu::USMBlob>;
using RemoteCLImage2D = TypedRemoteBlob<InferenceEngine::gpu::ClImage2DBlob>;
#ifdef _WIN32
using RemoteD3DBuffer = TypedRemoteBlob<InferenceEngine::gpu::D3DBufferBlob>;
using RemoteD3DSurface = TypedRemoteBlob<InferenceEngine::gpu::D3DSurface2DBlob>;
#else
using RemoteVASurface = TypedRemoteBlob<InferenceEngine::gpu::VASurfaceBlob>;
#endif
} // namespace intel_gpu
} // namespace ov
@@ -0,0 +1,152 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include "intel_gpu/runtime/lru_cache.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/legacy_remote_blob.hpp"
#include <ie_parameter.hpp>
#include <blob_factory.hpp>
#include <ie_remote_context.hpp>
#include <remote_utils.hpp>
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifdef _WIN32
# include <gpu/gpu_context_api_dx.hpp>
#else
# include <gpu/gpu_context_api_va.hpp>
#endif
#include <string>
#include <map>
#include <memory>
#include <atomic>
namespace ov {
namespace intel_gpu {
// Template class below is needed to allow proper cast of user contexts
// We have the following public classes hierarchy:
// RemoteContext
// |
// ClContext
// | |
// VAContext D3DContext
// So our implementation must allow casting of context object to proper type user type (ClContext, VAContext or D3DContext)
// Thus we introduce this template which have 3 instances with different base classes:
// RemoteContext
// |
// ---------- ClContext -----------
// | | |
// VAContext | D3DContext
// | | |
// RemoteVAContext RemoteCLContext RemoteD3DContext
//
// All these context types are just thin wrappers that calls common context internal impl (RemoteContextImpl)
template<typename PublicContextType>
class TypedRemoteContext : public PublicContextType {
public:
using Ptr = std::shared_ptr<TypedRemoteContext>;
explicit TypedRemoteContext(std::shared_ptr<RemoteContextImpl> impl) : m_impl(impl) {}
TypedRemoteContext(std::string device_name, std::vector<cldnn::device::ptr> devices)
: m_impl(std::make_shared<RemoteContextImpl>(device_name, devices)) {}
TypedRemoteContext(const std::map<std::string, RemoteContextImpl::Ptr>& known_contexts, const InferenceEngine::ParamMap& params)
: m_impl(std::make_shared<RemoteContextImpl>(known_contexts, params)) {}
InferenceEngine::ParamMap getParams() const override { return m_impl->get_property(); }
std::string getDeviceName() const noexcept override { return m_impl->get_device_name(); }
InferenceEngine::MemoryBlob::Ptr CreateHostBlob(const InferenceEngine::TensorDesc& desc) override {
auto new_tensor = m_impl->create_host_tensor(InferenceEngine::details::convertPrecision(desc.getPrecision()), ov::Shape(desc.getDims()));
return std::dynamic_pointer_cast<InferenceEngine::MemoryBlob>(make_blob_with_precision(desc, new_tensor->data()));
}
InferenceEngine::RemoteBlob::Ptr CreateBlob(const InferenceEngine::TensorDesc& desc, const InferenceEngine::ParamMap& params = {}) override {
auto new_tensor = m_impl->create_tensor(InferenceEngine::details::convertPrecision(desc.getPrecision()), ov::Shape(desc.getDims()), params);
auto tensor_impl = std::dynamic_pointer_cast<RemoteTensorImpl>(new_tensor._ptr);
OPENVINO_ASSERT(tensor_impl, "[GPU] Unexpected tensor impl type");
auto mem_type = tensor_impl->get_properties().at(ov::intel_gpu::shared_mem_type.name()).as<ov::intel_gpu::SharedMemType>();
if (mem_type == ov::intel_gpu::SharedMemType::OCL_BUFFER) {
return std::make_shared<RemoteCLbuffer>(tensor_impl, std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()));
} else if (mem_type == ov::intel_gpu::SharedMemType::USM_DEVICE_BUFFER ||
mem_type == ov::intel_gpu::SharedMemType::USM_HOST_BUFFER ||
mem_type == ov::intel_gpu::SharedMemType::USM_USER_BUFFER) {
return std::make_shared<RemoteUSMbuffer>(tensor_impl, std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()));
} else if (mem_type == ov::intel_gpu::SharedMemType::OCL_IMAGE2D) {
return std::make_shared<RemoteCLImage2D>(tensor_impl, std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()));
#ifdef _WIN32
} else if (mem_type == ov::intel_gpu::SharedMemType::DX_BUFFER) {
return std::make_shared<RemoteD3DBuffer>(tensor_impl, std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()));
} else if (mem_type == ov::intel_gpu::SharedMemType::VA_SURFACE) {
return std::make_shared<RemoteD3DSurface>(tensor_impl, std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()));
#else
} else if (mem_type == ov::intel_gpu::SharedMemType::VA_SURFACE) {
return std::make_shared<RemoteVASurface>(tensor_impl, std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()));
#endif
}
OPENVINO_THROW("[GPU] CreateBlob error: Unsupported memory type: ", mem_type);
}
RemoteContextImpl::Ptr get_impl() { return m_impl; }
private:
std::shared_ptr<RemoteContextImpl> m_impl;
};
using RemoteCLContext = TypedRemoteContext<InferenceEngine::gpu::ClContext>;
#ifdef _WIN32
using RemoteD3DContext = TypedRemoteContext<InferenceEngine::gpu::D3DContext>;
#else
using RemoteVAContext = TypedRemoteContext<InferenceEngine::gpu::VAContext>;
#endif
inline ov::SoPtr<ov::IRemoteContext> wrap_if_old_api(std::shared_ptr<RemoteContextImpl> new_impl, bool is_new_api) {
if (is_new_api) {
return new_impl;
} else {
auto remote_properties = new_impl->get_property();
auto context_type = remote_properties.at(ov::intel_gpu::context_type.name()).as<ov::intel_gpu::ContextType>();
if (context_type == ov::intel_gpu::ContextType::OCL) {
return ov::legacy_convert::convert_remote_context(std::make_shared<RemoteCLContext>(new_impl));
} else if (context_type == ov::intel_gpu::ContextType::VA_SHARED) {
#ifdef _WIN32
return ov::legacy_convert::convert_remote_context(std::make_shared<RemoteD3DContext>(new_impl));
#else
return ov::legacy_convert::convert_remote_context(std::make_shared<RemoteVAContext>(new_impl));
#endif
}
}
OPENVINO_THROW("[GPU] Unexpected context parameters");
}
inline RemoteContextImpl::Ptr get_context_impl(ov::SoPtr<ov::IRemoteContext> ptr) {
if (auto wrapper = std::dynamic_pointer_cast<InferenceEngine::IRemoteContextWrapper>(ptr._ptr)) {
auto legacy_context = wrapper->get_context();
if (auto legacy_context_impl = std::dynamic_pointer_cast<RemoteCLContext>(legacy_context)) {
return legacy_context_impl->get_impl();
#ifdef _WIN32
} else if (auto legacy_context_impl = std::dynamic_pointer_cast<RemoteD3DContext>(legacy_context)) {
return legacy_context_impl->get_impl();
#else
} else if (auto legacy_context_impl = std::dynamic_pointer_cast<RemoteVAContext>(legacy_context)) {
return legacy_context_impl->get_impl();
#endif
}
}
auto casted = std::dynamic_pointer_cast<RemoteContextImpl>(ptr._ptr);
OPENVINO_ASSERT(casted, "[GPU] Invalid remote context type. Can't cast to ov::intel_gpu::RemoteContext type");
return casted;
}
} // namespace intel_gpu
} // namespace ov
@@ -4,70 +4,64 @@
#pragma once
#include "openvino/runtime/iplugin.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include <map>
#include <string>
#include <memory>
#include "intel_gpu/runtime/engine.hpp"
#include <cpp_interfaces/interface/ie_iplugin_internal.hpp>
#include <cpp_interfaces/interface/ie_iexecutable_network_internal.hpp>
#include "intel_gpu/plugin/remote_context.hpp"
namespace ov {
namespace intel_gpu {
class Plugin : public InferenceEngine::IInferencePlugin {
struct impl;
std::shared_ptr<impl> _impl;
std::string default_device_id = "0";
// key: device_id, value: cldnn device
std::map<std::string, cldnn::device::ptr> device_map;
class Plugin : public ov::IPlugin {
private:
std::string m_default_device_id = "0";
std::map<std::string, cldnn::device::ptr> m_device_map;
std::map<std::string, ExecutionConfig> m_configs_map;
mutable std::map<std::string, RemoteCLContext::Ptr> m_default_contexts;
mutable std::map<std::string, std::shared_ptr<RemoteContextImpl>> m_default_contexts;
mutable std::once_flag m_default_contexts_once;
std::map<std::string, RemoteCLContext::Ptr> get_default_contexts() const;
std::map<std::string, std::shared_ptr<RemoteContextImpl>> get_default_contexts() const;
InferenceEngine::CNNNetwork clone_and_transform_model(const InferenceEngine::CNNNetwork& network,
const ExecutionConfig& config) const;
std::shared_ptr<ov::Model> clone_and_transform_model(const std::shared_ptr<const ov::Model>& network, const ExecutionConfig& config) const;
void transform_model(std::shared_ptr<ov::Model>& model, const ExecutionConfig& config) const;
void register_primitives();
std::string get_device_id_from_config(const std::map<std::string, std::string>& config) const;
std::string get_device_id(const std::map<std::string, std::string>& config) const;
RemoteCLContext::Ptr get_default_context(const std::string& device_id) const;
void register_primitives() const;
std::string get_device_id_from_config(const ov::AnyMap& config) const;
std::string get_device_id(const ov::AnyMap& config) const;
std::shared_ptr<RemoteContextImpl> get_default_context(const std::string& device_id) const;
std::vector<ov::PropertyName> get_caching_properties() const;
std::vector<ov::PropertyName> get_supported_properties() const;
std::vector<ov::PropertyName> get_supported_internal_properties() const;
std::vector<std::string> get_device_capabilities(const cldnn::device_info& info) const;
uint32_t get_optimal_batch_size(const std::map<std::string, InferenceEngine::Parameter>& options) const;
uint32_t get_max_batch_size(const std::map<std::string, InferenceEngine::Parameter>& options) const;
uint32_t get_optimal_batch_size(const ov::AnyMap& options) const;
uint32_t get_max_batch_size(const ov::AnyMap& options) const;
ov::AnyMap preprocess_config(const std::map<std::string, std::string>& orig_config) const;
ov::AnyMap preprocess_config(const ov::AnyMap& orig_config) const;
bool is_metric(const std::string& name) const;
ov::Any get_metric(const std::string& name, const ov::AnyMap& arguments) const;
public:
Plugin();
InferenceEngine::IExecutableNetworkInternal::Ptr LoadExeNetworkImpl(const InferenceEngine::CNNNetwork &network,
const std::map<std::string, std::string> &config) override;
std::shared_ptr<ov::ICompiledModel> compile_model(const std::shared_ptr<const ov::Model>& model,
const ov::AnyMap& properties) const override;
std::shared_ptr<ov::ICompiledModel> compile_model(const std::shared_ptr<const ov::Model>& model,
const ov::AnyMap& properties,
const ov::SoPtr<ov::IRemoteContext>& context) const override;
InferenceEngine::IExecutableNetworkInternal::Ptr LoadExeNetworkImpl(const InferenceEngine::CNNNetwork &network,
const std::shared_ptr<InferenceEngine::RemoteContext> &context,
const std::map<std::string, std::string> &config) override;
void SetConfig(const std::map<std::string, std::string> &config) override;
InferenceEngine::Parameter GetConfig(const std::string& name, const std::map<std::string, InferenceEngine::Parameter>& options) const override;
InferenceEngine::Parameter GetMetric(const std::string& name, const std::map<std::string, InferenceEngine::Parameter>& options) const override;
InferenceEngine::QueryNetworkResult QueryNetwork(const InferenceEngine::CNNNetwork& network,
const std::map<std::string, std::string>& config) const override;
InferenceEngine::IExecutableNetworkInternal::Ptr ImportNetwork(std::istream& networkModel,
const std::map<std::string, std::string>& config) override;
InferenceEngine::IExecutableNetworkInternal::Ptr ImportNetwork(std::istream& networkModel,
const std::shared_ptr<InferenceEngine::RemoteContext>& context,
const std::map<std::string, std::string>& config) override;
std::shared_ptr<InferenceEngine::RemoteContext> CreateContext(const InferenceEngine::ParamMap& params) override;
std::shared_ptr<InferenceEngine::RemoteContext> GetDefaultContext(const InferenceEngine::ParamMap& params) override;
void set_property(const ov::AnyMap& properties) override;
ov::Any get_property(const std::string& name, const ov::AnyMap& arguments) const override;
std::shared_ptr<ov::ICompiledModel> import_model(std::istream& model, const ov::AnyMap& properties) const override;
std::shared_ptr<ov::ICompiledModel> import_model(std::istream& model,
const ov::SoPtr<ov::IRemoteContext>& context,
const ov::AnyMap& properties) const override;
ov::SupportedOpsMap query_model(const std::shared_ptr<const ov::Model>& model,
const ov::AnyMap& properties) const override;
ov::SoPtr<ov::IRemoteContext> create_context(const ov::AnyMap& remote_properties) const override;
ov::SoPtr<ov::IRemoteContext> get_default_context(const ov::AnyMap& remote_properties) const override;
};
} // namespace intel_gpu
@@ -13,8 +13,6 @@
#include "intel_gpu/graph/topology.hpp"
#include "intel_gpu/graph/program.hpp"
#include <cpp/ie_cnn_network.h>
#include <vector>
#include <map>
#include <memory>
@@ -59,38 +57,28 @@ std::string layer_type_lower(const std::shared_ptr<ov::Node>& op);
std::string layer_type_name_ID(const std::shared_ptr<ov::Node>& op);
struct PerfCounter {
InferenceEngine::InferenceEngineProfileInfo::LayerStatus status;
bool isCPU;
uint64_t realTime_uSec;
uint64_t cpu_uSec;
uint32_t num;
std::string layerType;
std::string parentPrimitive;
ov::ProfilingInfo::Status status = ov::ProfilingInfo::Status::NOT_RUN;
bool isCPU = false;
uint64_t realTime_uSec = 0;
uint64_t cpu_uSec = 0;
uint32_t num = 0;
std::string layerType = "";
std::string parentPrimitive = "";
public:
PerfCounter()
: status(InferenceEngine::InferenceEngineProfileInfo::NOT_RUN)
, isCPU(false)
, realTime_uSec(0)
, cpu_uSec(0)
, num(0) {}
PerfCounter() = default;
long long realTime_avg() const { return (num == 0) ? 0 : realTime_uSec / num; }
long long cpu_avg() const { return (num == 0) ? 0 : cpu_uSec / num; }
};
class ProgramBuilder {
class ProgramBuilder final {
public:
ProgramBuilder(InferenceEngine::CNNNetwork& network, cldnn::engine& engine, const ExecutionConfig& config,
ProgramBuilder(std::shared_ptr<ov::Model> model, cldnn::engine& engine, const ExecutionConfig& config,
bool createTopologyOnly = false, bool partialBuild = false,
InferenceEngine::InputsDataMap* inputs = nullptr, InferenceEngine::OutputsDataMap* outputs = nullptr,
std::shared_ptr<ov::threading::IStreamsExecutor> task_executor = nullptr, bool innerProgram = false);
ProgramBuilder(cldnn::engine& engine, const ExecutionConfig& config,
InferenceEngine::InputsDataMap* inputs = nullptr, InferenceEngine::OutputsDataMap* outputs = nullptr);
ProgramBuilder(cldnn::engine& engine, const ExecutionConfig& config);
static const cldnn::primitive_id m_preProcessTag;
static const cldnn::primitive_id m_meanValuesTag;
static const cldnn::primitive_id m_workaroundTag;
static const cldnn::primitive_id m_preCustomLayerTag;
static const cldnn::primitive_id m_postCustomLayerTag;
@@ -100,38 +88,27 @@ public:
std::vector<cldnn::primitive_id> profiling_ids;
std::map<std::string, InferenceEngine::SizeVector> outputDims;
std::map<std::string, cldnn::layout> inputLayouts;
using BlobCacheKey = std::pair<const char*, std::vector<size_t>>;
std::map<BlobCacheKey, cldnn::primitive_id> blobMemCache;
CustomLayerMap m_custom_layers;
int m_max_batch;
int m_curBatch;
std::map<std::string, std::pair<int64_t, int64_t>> m_input_batch_dim;
std::map<std::string, int64_t> m_output_batch_dim;
std::shared_ptr<cldnn::program> get_compiled_program() const;
std::shared_ptr<cldnn::topology> get_topology() const { return m_topology; }
std::shared_ptr<cldnn::program> GetCompiledProgram(int program_id = 0);
const std::map<std::string, cldnn::layout>& GetInputLayouts() const { return inputLayouts; }
InferenceEngine::InputsDataMap GetNetworkInputs() const { return m_networkInputs; }
InferenceEngine::OutputsDataMap GetNetworkOutputs() const { return m_networkOutputs; }
const std::map<std::string, cldnn::layout>& get_input_layouts() const { return inputLayouts; }
cldnn::engine& get_engine() const { return m_engine; }
const ExecutionConfig& get_config() const { return m_config; }
int GetMaxBatchSizeForSingleProgram();
bool IsOpSupported(const InferenceEngine::CNNNetwork& network, const std::shared_ptr<ngraph::Node>& op);
bool IsDynBatchModel(const std::shared_ptr<ov::Model>& model,
std::map<std::string, ov::PartialShape>& shapes,
std::map<std::string, std::pair<int64_t, int64_t>>& batch_dim);
bool is_op_supported(const std::shared_ptr<ov::Node>& op);
// Profiling utils
void init_profile_info(const cldnn::primitive& prim);
// Graph construction helpers
std::vector<cldnn::input_info> GetInputInfo(const std::shared_ptr<ngraph::Node>& op) const;
std::vector<cldnn::input_info> GetInputInfo(const std::shared_ptr<ov::Node>& op) const;
using factory_t = std::function<void(ProgramBuilder&, const std::shared_ptr<ngraph::Node>&)>;
using factories_map_t = std::map<ngraph::DiscreteTypeInfo, factory_t>;
using factory_t = std::function<void(ProgramBuilder&, const std::shared_ptr<ov::Node>&)>;
using factories_map_t = std::map<ov::DiscreteTypeInfo, factory_t>;
template<typename OpType>
static void RegisterFactory(factory_t func) {
@@ -142,13 +119,12 @@ public:
}
template<typename PType, typename = typename std::enable_if<!is_smart_pointer<PType>::value>::type>
void add_primitive(const ngraph::Node& op, PType prim, std::vector<std::string> aliases = {}) {
void add_primitive(const ov::Node& op, PType prim, std::vector<std::string> aliases = {}) {
add_primitive(op, std::static_pointer_cast<cldnn::primitive>(std::make_shared<PType>(prim)), std::move(aliases));
}
void add_primitive(const ngraph::Node& op, std::shared_ptr<cldnn::primitive> prim, std::vector<std::string> aliases = {});
void add_primitive(const ov::Node& op, std::shared_ptr<cldnn::primitive> prim, std::vector<std::string> aliases = {});
std::shared_ptr<cldnn::topology> GetTopology() const { return m_topology; }
using variables_state_info_map = std::map<std::string, std::set<cldnn::layout>>;
@@ -157,21 +133,20 @@ public:
const variables_state_info_map& GetVariablesStatesInfo() const { return m_variablesStateInfo; }
bool use_new_shape_infer() const { return allow_new_shape_infer; }
bool requires_new_shape_infer(const ngraph::Node& op) const;
bool requires_new_shape_infer(const ov::Node& op) const;
std::shared_ptr<ov::threading::IStreamsExecutor> get_task_executor() { return m_task_executor; }
std::shared_ptr<ov::threading::IStreamsExecutor> get_task_executor() const { return m_task_executor; }
private:
static factories_map_t factories_map;
std::vector<std::shared_ptr<cldnn::program>> m_programs;
std::shared_ptr<cldnn::program> m_program;
ExecutionConfig m_config;
cldnn::engine& m_engine;
static std::mutex m_mutex;
std::shared_ptr<cldnn::topology> m_topology;
InferenceEngine::InputsDataMap m_networkInputs;
InferenceEngine::OutputsDataMap m_networkOutputs;
variables_state_info_map m_variablesStateInfo;
CustomLayerMap m_custom_layers;
bool allow_new_shape_infer = false;
@@ -182,31 +157,28 @@ private:
void EnableQueryMode() { queryMode = true; }
void DisableQueryMode() { queryMode = false; }
void PrepareBuild(InferenceEngine::InputsDataMap networkInputs, InferenceEngine::OutputsDataMap networkOutputs);
void CleanupBuild();
void prepare_build();
void cleanup_build();
// TODO(eunsoo): remove createTopolpgyOnly argument and add another method to create topology from ngraph function
std::shared_ptr<cldnn::program> BuildProgram(const std::vector<std::shared_ptr<ngraph::Node>>& ops,
InferenceEngine::InputsDataMap networkInputs,
InferenceEngine::OutputsDataMap networkOutputs,
bool createTopologyOnly = false, bool partialBuild = false, bool innerProgram = false);
std::shared_ptr<cldnn::program> build(const std::vector<std::shared_ptr<ov::Node>>& ops,
bool createTopologyOnly = false, bool partialBuild = false, bool innerProgram = false);
void CreateSingleLayerPrimitive(cldnn::topology& topology, const std::shared_ptr<ngraph::Node>& op);
void ChangeInputBatch(int batch);
void CreateSingleLayerPrimitive(cldnn::topology& topology, const std::shared_ptr<ov::Node>& op);
};
void CreateCustomOp(ProgramBuilder& p, const std::shared_ptr<ngraph::Node>& node, CustomLayerPtr customLayer);
void CreateUnaryEltwiseOp(ProgramBuilder& p, const std::shared_ptr<ngraph::Node>& node,
void CreateCustomOp(ProgramBuilder& p, const std::shared_ptr<ov::Node>& node, CustomLayerPtr customLayer);
void CreateUnaryEltwiseOp(ProgramBuilder& p, const std::shared_ptr<ov::Node>& node,
cldnn::activation_func func, cldnn::activation_additional_params params);
void CreateElementwiseOp(ProgramBuilder& p,
const std::shared_ptr<ngraph::Node>& node,
const std::shared_ptr<ov::Node>& node,
cldnn::eltwise_mode mode,
std::vector<float> coefficients = {},
bool pythondiv = true);
bool IsNodeOnConstPath(const std::shared_ptr<ngraph::Node>& node);
bool IsNodeOnConstPath(const std::shared_ptr<ov::Node>& node);
void validate_inputs_count(const std::shared_ptr<ngraph::Node>& op, std::vector<size_t> possible_inputs_count);
void validate_inputs_count(const std::shared_ptr<ov::Node>& op, std::vector<size_t> possible_inputs_count);
inline bool ends_with(const std::string& value, const std::string& suffix) {
if (suffix.size() > value.size())
@@ -4,95 +4,39 @@
#pragma once
#include "intel_gpu/plugin/remote_context.hpp"
#include "openvino/runtime/so_ptr.hpp"
#include <string>
#include <map>
#include <memory>
#include <atomic>
namespace ov {
namespace intel_gpu {
class RemoteBlobImpl;
class RemoteTensorImpl;
class RemoteContextImpl;
class RemoteAllocator : public InferenceEngine::IAllocator {
protected:
friend class RemoteBlobImpl;
std::atomic_flag _lock;
std::map<void*, const RemoteBlobImpl*> m_lockedBlobs;
void regLockedBlob(void* handle, const RemoteBlobImpl* blob);
public:
using Ptr = std::shared_ptr<RemoteAllocator>;
RemoteAllocator() { _lock.clear(std::memory_order_relaxed); }
/**
* @brief Maps handle to heap memory accessible by any memory manipulation routines.
* @return Generic pointer to memory
*/
void* lock(void* handle, InferenceEngine::LockOp = InferenceEngine::LOCK_FOR_WRITE) noexcept override { return handle; };
/**
* @brief Unmaps memory by handle with multiple sequential mappings of the same handle.
* The multiple sequential mappings of the same handle are suppose to get the same
* result while there isn't a ref counter supported.
*/
void unlock(void* handle) noexcept override;
/**
* @brief Allocates memory
* @param size The size in bytes to allocate
* @return Handle to the allocated resource
*/
void* alloc(size_t size) noexcept override { return nullptr; }
/**
* @brief Releases handle and all associated memory resources which invalidates the handle.
* @return false if handle cannot be released, otherwise - true.
*/
bool free(void* handle) noexcept override { return true; }
void lock() {
while (_lock.test_and_set(std::memory_order_acquire)) {}
}
void unlock() {
_lock.clear(std::memory_order_release);
}
};
class USMHostAllocator : public InferenceEngine::IAllocator {
protected:
InferenceEngine::gpu::USMBlob::Ptr _usm_host_blob = nullptr;
InferenceEngine::gpu::ClContext::Ptr _context = nullptr;
class USMHostAllocator final {
private:
ov::SoPtr<RemoteTensorImpl> _usm_host_tensor = { nullptr, nullptr };
std::shared_ptr<RemoteContextImpl> _context = nullptr;
public:
using Ptr = std::shared_ptr<USMHostAllocator>;
USMHostAllocator(InferenceEngine::gpu::ClContext::Ptr context) : _context(context) { }
/**
* @brief Maps handle to heap memory accessible by any memory manipulation routines.
* @return Generic pointer to memory
*/
void* lock(void* handle, InferenceEngine::LockOp = InferenceEngine::LOCK_FOR_WRITE) noexcept override;
/**
* @brief Unmaps memory by handle with multiple sequential mappings of the same handle.
* The multiple sequential mappings of the same handle are suppose to get the same
* result while there isn't a ref counter supported.
*/
void unlock(void* handle) noexcept override;
explicit USMHostAllocator(std::shared_ptr<RemoteContextImpl> context) : _context(context) { }
/**
* @brief Allocates memory
* @param size The size in bytes to allocate
* @return Handle to the allocated resource
*/
void* alloc(size_t size) noexcept override;
void* allocate(const size_t bytes, const size_t alignment = alignof(max_align_t)) noexcept;
/**
* @brief Releases handle and all associated memory resources which invalidates the handle.
* @return false if handle cannot be released, otherwise - true.
*/
bool free(void* handle) noexcept override;
bool deallocate(void* handle, const size_t bytes, size_t alignment = alignof(max_align_t)) noexcept;
bool is_equal(const USMHostAllocator& other) const;
};
} // namespace intel_gpu
@@ -1,176 +0,0 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifdef _WIN32
# include <gpu/gpu_context_api_dx.hpp>
#else
# include <gpu/gpu_context_api_va.hpp>
#endif
#include <string>
#include <map>
#include <memory>
namespace ov {
namespace intel_gpu {
class RemoteContextImpl;
class RemoteBlobImpl : public InferenceEngine::gpu::details::param_map_obj_getter {
friend class RemoteAllocator;
public:
explicit RemoteBlobImpl(InferenceEngine::gpu::ClContext::Ptr context,
cldnn::stream& stream,
const cldnn::layout& layout,
cldnn::shared_handle mem = nullptr,
cldnn::shared_surface surf = 0,
uint32_t plane = 0,
BlobType mem_type = BlobType::BT_BUF_INTERNAL);
void allocate();
bool deallocate() noexcept;
InferenceEngine::ParamMap getParams() const;
std::string getDeviceName() const noexcept;
std::shared_ptr<InferenceEngine::RemoteContext> getContext() const noexcept;
InferenceEngine::LockedMemory<void> buffer() noexcept;
InferenceEngine::LockedMemory<const void> cbuffer() const noexcept;
InferenceEngine::LockedMemory<void> rwmap() noexcept;
InferenceEngine::LockedMemory<const void> rmap() const noexcept;
InferenceEngine::LockedMemory<void> wmap() noexcept;
const std::shared_ptr<InferenceEngine::IAllocator> &getAllocator() const noexcept;
void *getHandle() const noexcept { return _handle; }
void reinterpret(const cldnn::layout& new_layout);
bool is_allocated() const noexcept;
bool is_locked() const noexcept;
cldnn::memory::ptr get_memory() {
auto engine = m_memory_object->get_engine();
return engine->reinterpret_buffer(*m_memory_object, m_layout);
}
cldnn::memory::ptr get_original_memory() {
return m_memory_object;
}
void setShape(const InferenceEngine::SizeVector& dims);
protected:
std::shared_ptr<InferenceEngine::IAllocator> m_allocator;
InferenceEngine::gpu::ClContext::Ptr m_context;
cldnn::stream& m_stream;
// constructor stuff
cldnn::shared_handle m_mem;
cldnn::shared_surface m_surf;
uint32_t m_plane;
cldnn::layout m_layout;
BlobType m_mem_type;
size_t m_hash;
cldnn::memory::ptr m_memory_object;
mutable std::mutex lockedMutex;
mutable size_t lockedCounter;
mutable std::unique_ptr<cldnn::mem_lock<uint8_t>> lockedHolder;
mutable void* _handle;
void lock() const;
void unlock() const;
bool is_shared() const;
bool supports_caching() const;
};
template<typename TpublicAPI>
class TypedRemoteBlob : public TpublicAPI {
public:
using Ptr = std::shared_ptr<TypedRemoteBlob>;
explicit TypedRemoteBlob(InferenceEngine::gpu::ClContext::Ptr context,
cldnn::stream& stream,
const InferenceEngine::TensorDesc& desc,
const cldnn::layout& layout,
cldnn::shared_handle mem = nullptr,
cldnn::shared_surface surf = 0,
uint32_t plane = 0,
BlobType mem_type = BlobType::BT_BUF_INTERNAL)
: TpublicAPI(desc)
, _impl(context, stream, layout, mem, surf, plane, mem_type) {}
void allocate() noexcept override {
try {
if (!_impl.is_allocated())
_impl.allocate();
} catch (...) {}
}
bool deallocate() noexcept override { return _impl.deallocate(); }
InferenceEngine::ParamMap getParams() const override { return _impl.getParams(); }
std::string getDeviceName() const noexcept override { return _impl.getDeviceName(); }
std::shared_ptr<InferenceEngine::RemoteContext> getContext() const noexcept override { return _impl.getContext(); }
InferenceEngine::LockedMemory<void> buffer() noexcept override { return _impl.buffer(); }
InferenceEngine::LockedMemory<const void> cbuffer() const noexcept override { return _impl.cbuffer(); }
InferenceEngine::LockedMemory<void> rwmap() noexcept override { return _impl.rwmap(); }
InferenceEngine::LockedMemory<const void> rmap() const noexcept override { return _impl.rmap(); }
InferenceEngine::LockedMemory<void> wmap()noexcept override { return _impl.wmap(); }
RemoteBlobImpl* getImpl() { return &_impl; }
void setShape(const InferenceEngine::SizeVector& dims) override { _impl.setShape(dims); }
protected:
const std::shared_ptr<InferenceEngine::IAllocator> &getAllocator() const noexcept override { return _impl.getAllocator(); }
void *getHandle() const noexcept override { return _impl.getHandle(); }
RemoteBlobImpl _impl;
};
using RemoteCLbuffer = TypedRemoteBlob<InferenceEngine::gpu::ClBufferBlob>;
using RemoteUSMbuffer = TypedRemoteBlob<InferenceEngine::gpu::USMBlob>;
using RemoteCLImage2D = TypedRemoteBlob<InferenceEngine::gpu::ClImage2DBlob>;
#ifdef _WIN32
using RemoteD3DBuffer = TypedRemoteBlob<InferenceEngine::gpu::D3DBufferBlob>;
using RemoteD3DSurface = TypedRemoteBlob<InferenceEngine::gpu::D3DSurface2DBlob>;
#else
using RemoteVASurface = TypedRemoteBlob<InferenceEngine::gpu::VASurfaceBlob>;
#endif
inline RemoteBlobImpl* getBlobImpl(InferenceEngine::gpu::ClBlob* blobPtr) {
#ifdef _WIN32
{
auto ptr = blobPtr->as<RemoteD3DSurface>();
if (ptr) return ptr->getImpl();
}
{
auto ptr = blobPtr->as<RemoteD3DBuffer>();
if (ptr) return ptr->getImpl();
}
#else
{
auto ptr = blobPtr->as<RemoteVASurface>();
if (ptr) return ptr->getImpl();
}
#endif
{
auto ptr = blobPtr->as<RemoteCLbuffer>();
if (ptr) return ptr->getImpl();
}
{
auto ptr = blobPtr->as<RemoteCLImage2D>();
if (ptr) return ptr->getImpl();
}
{
auto ptr = blobPtr->as<RemoteUSMbuffer>();
if (ptr) return ptr->getImpl();
}
return nullptr;
}
} // namespace intel_gpu
} // namespace ov
@@ -4,25 +4,23 @@
#pragma once
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include "intel_gpu/runtime/lru_cache.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#include <ie_parameter.hpp>
#include <cpp_interfaces/interface/ie_iplugin_internal.hpp>
#include <blob_factory.hpp>
#include <ie_remote_context.hpp>
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifdef _WIN32
# include <gpu/gpu_context_api_dx.hpp>
# include <openvino/runtime/intel_gpu/ocl/dx.hpp>
#else
# include <gpu/gpu_context_api_va.hpp>
# include <openvino/runtime/intel_gpu/ocl/va.hpp>
#endif
#include "openvino/runtime/iremote_context.hpp"
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include "intel_gpu/runtime/lru_cache.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#include <string>
#include <map>
@@ -32,150 +30,50 @@
namespace ov {
namespace intel_gpu {
enum class BlobType {
BT_EMPTY,
BT_BUF_INTERNAL,
BT_BUF_SHARED,
BT_USM_SHARED,
BT_USM_HOST_INTERNAL,
BT_USM_DEVICE_INTERNAL,
BT_IMG_SHARED,
BT_SURF_SHARED,
BT_DX_BUF_SHARED,
};
template <typename Result>
Result extract_object(const InferenceEngine::ParamMap& params, const std::string& key) {
auto itrHandle = params.find(key);
OPENVINO_ASSERT(itrHandle != params.end(), "[GPU] No parameter ", key, " found in ParamsMap");
return itrHandle->second.as<Result>();
}
class RemoteContextImpl {
class RemoteContextImpl : public ov::IRemoteContext {
public:
enum ContextType {
OCL,
DEV_SHARED
};
using Ptr = std::shared_ptr<RemoteContextImpl>;
using CPtr = std::shared_ptr<const RemoteContextImpl>;
RemoteContextImpl(std::string device_name, std::vector<cldnn::device::ptr> devices);
RemoteContextImpl(const std::vector<RemoteContextImpl::Ptr>& known_contexts, const InferenceEngine::ParamMap& params);
RemoteContextImpl(const std::string& device_name, std::vector<cldnn::device::ptr> devices);
RemoteContextImpl(const std::map<std::string, RemoteContextImpl::Ptr>& known_contexts, const ov::AnyMap& params);
const std::string& get_device_name() const override;
const ov::AnyMap& get_property() const override;
ov::SoPtr<ov::ITensor> create_host_tensor(const ov::element::Type type, const ov::Shape& shape) override;
ov::SoPtr<ov::IRemoteTensor> create_tensor(const ov::element::Type& type, const ov::Shape& shape, const ov::AnyMap& params) override;
InferenceEngine::ParamMap get_params() const;
std::string get_device_name() const noexcept;
InferenceEngine::MemoryBlob::Ptr create_host_blob(InferenceEngine::gpu::ClContext::Ptr public_context, const InferenceEngine::TensorDesc& desc);
InferenceEngine::RemoteBlob::Ptr create_blob(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
const InferenceEngine::ParamMap& params = {});
cldnn::engine& get_engine() { return *m_engine; }
InferenceEngine::gpu_handle_param get_external_queue() const { return m_external_queue; }
ov::intel_gpu::gpu_handle_param get_external_queue() const { return m_external_queue; }
cldnn::memory::ptr try_get_cached_memory(size_t hash);
void add_to_cache(size_t hash, cldnn::memory::ptr memory);
private:
std::string get_device_name(const std::vector<RemoteContextImpl::Ptr>& known_contexts,
const cldnn::device::ptr current_device);
InferenceEngine::RemoteBlob::Ptr reuse_surface(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
const InferenceEngine::ParamMap& params);
InferenceEngine::RemoteBlob::Ptr reuse_memory(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
cldnn::shared_handle mem,
BlobType blob_type);
InferenceEngine::RemoteBlob::Ptr create_buffer(InferenceEngine::gpu::ClContext::Ptr public_context, const InferenceEngine::TensorDesc& desc);
InferenceEngine::RemoteBlob::Ptr create_usm(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
BlobType alloc_type);
void check_if_shared();
std::shared_ptr<RemoteContextImpl> get_this_shared_ptr();
std::string get_device_name(const std::map<std::string, RemoteContextImpl::Ptr>& known_contexts, const cldnn::device::ptr current_device) const;
std::shared_ptr<ov::IRemoteTensor> reuse_surface(const ov::element::Type type, const ov::Shape& shape, const ov::AnyMap& params);
std::shared_ptr<ov::IRemoteTensor> reuse_memory(const ov::element::Type type, const ov::Shape& shape, cldnn::shared_handle mem, TensorType tensor_type);
std::shared_ptr<ov::IRemoteTensor> create_buffer(const ov::element::Type type, const ov::Shape& shape);
std::shared_ptr<ov::IRemoteTensor> create_usm(const ov::element::Type type, const ov::Shape& shape, TensorType alloc_type);
void check_if_shared() const;
void init_properties();
std::shared_ptr<cldnn::engine> m_engine;
InferenceEngine::gpu_handle_param m_va_display;
InferenceEngine::gpu_handle_param m_external_queue;
static const size_t cache_capacity = 100;
ov::intel_gpu::gpu_handle_param m_va_display = nullptr;
ov::intel_gpu::gpu_handle_param m_external_queue = nullptr;
ContextType m_type;
ContextType m_type = ContextType::OCL;
std::string m_device_name = "";
const std::string m_plugin_name;
cldnn::LruCache<size_t, cldnn::memory::ptr> m_memory_cache;
static const size_t cache_capacity = 100;
cldnn::LruCache<size_t, cldnn::memory::ptr> m_memory_cache = cldnn::LruCache<size_t, cldnn::memory::ptr>(cache_capacity);
std::mutex m_cache_mutex;
ov::AnyMap properties;
};
// Template class below is needed to allow proper cast of user contexts
// We have the following public classes hierarchy:
// RemoteContext
// |
// ClContext
// | |
// VAContext D3DContext
// So our implementation must allow casting of context object to proper type user type (ClContext, VAContext or D3DContext)
// Thus we introduce this template which have 3 instances with different base classes:
// RemoteContext
// |
// ---------- ClContext -----------
// | | |
// VAContext | D3DContext
// | | |
// RemoteVAContext RemoteCLContext RemoteD3DContext
//
// All these context types are just thin wrappers that calls common context internal impl (RemoteContextImpl)
template<typename PublicContextType>
class TypedRemoteContext : public PublicContextType {
public:
using Ptr = std::shared_ptr<TypedRemoteContext>;
TypedRemoteContext(std::string device_name, std::vector<cldnn::device::ptr> devices)
: m_impl(std::make_shared<RemoteContextImpl>(device_name, devices)) {}
TypedRemoteContext(const std::vector<RemoteContextImpl::Ptr>& known_contexts, const InferenceEngine::ParamMap& params)
: m_impl(std::make_shared<RemoteContextImpl>(known_contexts, params)) {}
InferenceEngine::ParamMap getParams() const override { return m_impl->get_params(); }
std::string getDeviceName() const noexcept override { return m_impl->get_device_name(); }
InferenceEngine::MemoryBlob::Ptr CreateHostBlob(const InferenceEngine::TensorDesc& desc) override {
return m_impl->create_host_blob(std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()), desc);
}
InferenceEngine::RemoteBlob::Ptr CreateBlob(const InferenceEngine::TensorDesc& desc, const InferenceEngine::ParamMap& params = {}) override {
return m_impl->create_blob(std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(this->shared_from_this()), desc, params);
}
RemoteContextImpl::Ptr get_impl() { return m_impl; }
private:
std::shared_ptr<RemoteContextImpl> m_impl;
};
using RemoteCLContext = TypedRemoteContext<InferenceEngine::gpu::ClContext>;
#ifdef _WIN32
using RemoteD3DContext = TypedRemoteContext<InferenceEngine::gpu::D3DContext>;
#else
using RemoteVAContext = TypedRemoteContext<InferenceEngine::gpu::VAContext>;
#endif
inline std::shared_ptr<RemoteContextImpl> get_context_impl(InferenceEngine::gpu::ClContext::Ptr context) {
OPENVINO_ASSERT(context != nullptr, "[GPU] Couldn't get impl from invalid context object");
#ifdef _WIN32
if (auto ptr = context->as<RemoteD3DContext>())
return ptr->get_impl();
#else
if (auto ptr = context->as<RemoteVAContext>())
return ptr->get_impl();
#endif
if (auto ptr = context->as<RemoteCLContext>())
return ptr->get_impl();
OPENVINO_ASSERT(false, "[GPU] Couldn't get context impl from public context object.");
}
inline std::shared_ptr<RemoteContextImpl> get_context_impl(InferenceEngine::RemoteContext::Ptr context) {
OPENVINO_ASSERT(context != nullptr, "[GPU] Couldn't get impl from invalid context object");
auto casted = std::dynamic_pointer_cast<InferenceEngine::gpu::ClContext>(context);
OPENVINO_ASSERT(casted != nullptr, "[GPU] Couldn't get context impl: Context type is not ClContext or it's derivatives");
return get_context_impl(casted);
}
} // namespace intel_gpu
} // namespace ov
@@ -0,0 +1,84 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#ifndef NOMINMAX
# define NOMINMAX
#endif
#ifdef _WIN32
# include <openvino/runtime/intel_gpu/ocl/dx.hpp>
#else
# include <openvino/runtime/intel_gpu/ocl/va.hpp>
#endif
#include "openvino/runtime/iremote_tensor.hpp"
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#include <string>
#include <map>
#include <memory>
namespace ov {
namespace intel_gpu {
class RemoteContextImpl;
class RemoteTensorImpl : public ov::IRemoteTensor {
friend class RemoteAllocator;
public:
RemoteTensorImpl(std::shared_ptr<RemoteContextImpl> context,
const ov::Shape& shape,
const ov::element::Type& element_type,
TensorType mem_type = TensorType::BT_BUF_INTERNAL,
cldnn::shared_handle mem = nullptr,
cldnn::shared_surface surf = 0,
uint32_t plane = 0);
~RemoteTensorImpl() override;
const AnyMap& get_properties() const override;
const std::string& get_device_name() const override;
void set_shape(ov::Shape shape) override;
const ov::element::Type& get_element_type() const override;
const ov::Shape& get_shape() const override;
const ov::Strides& get_strides() const override;
void allocate();
bool deallocate() noexcept;
bool is_allocated() const noexcept;
bool is_surface() const noexcept;
cldnn::memory::ptr get_memory() const;
cldnn::memory::ptr get_original_memory() const;
std::shared_ptr<RemoteContextImpl> get_context() const;
private:
std::shared_ptr<RemoteContextImpl> m_context;
ov::element::Type m_element_type;
ov::Shape m_shape;
ov::Strides m_strides{};
ov::AnyMap m_properties;
cldnn::memory::ptr m_memory_object = nullptr;
cldnn::layout m_layout;
TensorType m_mem_type;
cldnn::shared_handle m_mem;
cldnn::shared_surface m_surf;
uint32_t m_plane;
size_t m_hash = 0;
bool is_shared() const;
bool supports_caching() const;
void update_strides();
void init_properties();
};
} // namespace intel_gpu
} // namespace ov
@@ -0,0 +1,109 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "openvino/runtime/isync_infer_request.hpp"
#include "intel_gpu/plugin/graph.hpp"
#include "intel_gpu/plugin/remote_tensor.hpp"
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <atomic>
namespace ov {
namespace intel_gpu {
class CompiledModel;
enum class TensorOwner : uint8_t {
USER = 0,
PLUGIN = 1
};
struct TensorWrapper {
std::shared_ptr<ov::ITensor> ptr;
TensorOwner owner;
};
class SyncInferRequest : public ov::ISyncInferRequest {
public:
using Ptr = std::shared_ptr<SyncInferRequest>;
explicit SyncInferRequest(const std::shared_ptr<const CompiledModel>& compiled_model);
SyncInferRequest(const SyncInferRequest &) = delete;
~SyncInferRequest() override = default;
void infer() override;
std::vector<ov::ProfilingInfo> get_profiling_info() const override;
std::vector<ov::SoPtr<ov::IVariableState>> query_state() const override;
void set_tensor(const ov::Output<const ov::Node>& port, const ov::SoPtr<ov::ITensor>& tensor) override;
void set_tensors_impl(const ov::Output<const ov::Node> port, const std::vector<ov::SoPtr<ov::ITensor>>& tensors) override;
ov::SoPtr<ov::ITensor> get_tensor(const ov::Output<const ov::Node>& port) const override;
void set_task_executor(const std::shared_ptr<ov::threading::ITaskExecutor>& task_executor);
void setup_stream_graph();
void enqueue_notify();
void wait_notify();
void enqueue();
void wait();
bool use_external_queue() const { return m_use_external_queue; }
private:
void check_tensors() const override;
std::unordered_map<std::string, TensorWrapper> m_user_inputs;
std::unordered_map<std::string, TensorWrapper> m_user_outputs;
std::unordered_map<std::string, TensorWrapper> m_plugin_inputs;
std::unordered_map<std::string, TensorWrapper> m_plugin_outputs;
std::unordered_map<std::string, ov::Output<const ov::Node>> m_input_ports_map;
std::unordered_map<std::string, ov::Output<const ov::Node>> m_output_ports_map;
std::unordered_map<std::string, std::string> m_output_names_map;
std::map<cldnn::primitive_id, cldnn::network_output> m_internal_outputs;
std::shared_ptr<Graph> m_graph;
RemoteContextImpl::Ptr m_context = nullptr;
std::shared_ptr<ov::threading::IStreamsExecutor> m_stream_executor = nullptr;
bool m_enable_profiling = false;
bool m_use_external_queue = false;
std::vector<cldnn::event::ptr> prepare_input(const std::string& name, const ov::Output<const ov::Node>& port, const TensorWrapper& user_tensor_wrapper);
std::vector<cldnn::event::ptr> prepare_output(const std::string& name, const ov::Output<const ov::Node>& port, const TensorWrapper& user_tensor_wrapper);
std::vector<cldnn::event::ptr> prepare_batched_input(const std::string& name,
const ov::Output<const ov::Node>& port,
const std::vector<ov::SoPtr<ov::ITensor>>& user_tensors);
TensorWrapper create_or_share_device_tensor(const TensorWrapper& user_tensor_wrapper,
const std::string& name,
const ov::PartialShape& pshape,
ov::element::Type element_type,
bool need_lockable_mem) const;
std::shared_ptr<ov::ITensor> reinterpret_device_tensor(std::shared_ptr<RemoteTensorImpl> tensor, const ov::Shape new_shape) const;
std::shared_ptr<ov::ITensor> create_host_tensor(const ov::PartialShape& port_shape, const ov::element::Type& port_element_type) const;
std::shared_ptr<ov::ITensor> create_device_tensor(const ov::Shape& pshape, ov::element::Type element_type,
bool need_lockable_memory = false, void* mem_ptr = nullptr) const;
std::shared_ptr<ov::ITensor> create_shared_device_tensor(const ov::Shape& pshape, ov::element::Type element_type, void* usm_host_mem) const;
void allocate_inputs();
void allocate_outputs();
void allocate_states();
void allocate_input(const ov::Output<const ov::Node>& port, const std::string& name);
void allocate_output(const ov::Output<const ov::Node>& port, const std::string& name);
cldnn::event::ptr copy_output_data(cldnn::memory::ptr src, const ov::ITensor& dst) const;
void init_mappings(bool is_legacy_api);
bool is_batched_input(const ov::Output<const ov::Node>& port) const;
};
} // namespace intel_gpu
} // namespace ov
@@ -3,45 +3,24 @@
//
#pragma once
#include <cpp_interfaces/interface/ie_ivariable_state_internal.hpp>
#include "openvino/runtime/ivariable_state.hpp"
#include "intel_gpu/plugin/graph.hpp"
#include <functional>
namespace ov {
namespace intel_gpu {
class VariableState : public InferenceEngine::IVariableStateInternal {
class VariableState : public ov::IVariableState {
public:
VariableState(const std::string& name, const std::vector<cldnn::network::VariableState::Ptr>& states,
cldnn::engine& engine, int currentBatch);
VariableState(const std::string& name, cldnn::network::VariableState::Ptr states, cldnn::engine& engine);
/**
* @brief Reset internal variable state for relevant infer request, to a value specified as
* default for according `ReadValue` node
*/
void Reset() override;
/**
* @brief Sets the new state for the next inference
* @param newState A new state
*/
void SetState(const InferenceEngine::Blob::Ptr &newState) override;
/**
* @brief Returns the value of the variable state.
* @return The value of the variable state
*/
InferenceEngine::Blob::CPtr GetState() const override;
protected:
InferenceEngine::SizeVector AggregateShape(const cldnn::layout &layout);
void IterateOverStates(std::function<void(cldnn::network::VariableState&)> f) const;
void reset() override;
void set_state(const ov::SoPtr<ov::ITensor>& state) override;
const ov::SoPtr<ov::ITensor>& get_state() const override;
private:
int currentBatch_;
std::vector<cldnn::network::VariableState::Ptr> states_;
InferenceEngine::TensorDesc desc_;
cldnn::engine& engine_;
cldnn::network::VariableState::Ptr m_variable_state;
cldnn::engine& m_engine;
};
} // namespace intel_gpu
@@ -36,24 +36,20 @@ struct convert_color : public primitive_base<convert_color> {
/// @param input_color_format Color to convert from.
/// @param output_color_format Color to convert to.
/// @param mem_type Memory type.
/// @param output_layout Requested memory layout.
convert_color(const primitive_id& id,
const std::vector<input_info>& inputs,
const color_format input_color_format,
const color_format output_color_format,
const memory_type mem_type,
const layout& output_layout,
const padding& output_padding = padding())
: primitive_base(id, inputs, {output_padding}),
input_color_format(input_color_format),
output_color_format(output_color_format),
mem_type(mem_type),
output_layout(output_layout) {}
mem_type(mem_type) {}
color_format input_color_format = color_format::RGB;
color_format output_color_format = color_format::RGB;
memory_type mem_type = memory_type::buffer;
layout output_layout;
size_t hash() const override {
size_t seed = primitive::hash();
@@ -71,8 +67,7 @@ struct convert_color : public primitive_base<convert_color> {
return input_color_format == rhs_casted.input_color_format &&
output_color_format == rhs_casted.output_color_format &&
mem_type == rhs_casted.mem_type &&
output_layout == rhs_casted.output_layout;
mem_type == rhs_casted.mem_type;
}
void save(BinaryOutputBuffer& ob) const override {
@@ -80,7 +75,6 @@ struct convert_color : public primitive_base<convert_color> {
ob << make_data(&input_color_format, sizeof(color_format));
ob << make_data(&output_color_format, sizeof(color_format));
ob << make_data(&mem_type, sizeof(memory_type));
ob << output_layout;
}
void load(BinaryInputBuffer& ib) override {
@@ -88,7 +82,6 @@ struct convert_color : public primitive_base<convert_color> {
ib >> make_data(&input_color_format, sizeof(color_format));
ib >> make_data(&output_color_format, sizeof(color_format));
ib >> make_data(&mem_type, sizeof(memory_type));
ib >> output_layout;
}
};
} // namespace cldnn
@@ -0,0 +1,19 @@
// Copyright (C) 2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <string>
#include <vector>
#include "openvino/util/file_util.hpp"
namespace ov {
namespace intel_gpu {
// Version of save_binary that don't trow an exception if attempt to open file fails
void save_binary(const std::string& path, std::vector<uint8_t> binary);
} // namespace intel_gpu
} // namespace ov
@@ -235,7 +235,7 @@ inline data_types element_type_to_data_type(ov::element::Type t) {
case ov::element::Type_t::i64:
return cldnn::data_types::i64;
case ov::element::Type_t::boolean:
return cldnn::data_types::i8;
return cldnn::data_types::u8;
case ov::element::Type_t::u1:
return cldnn::data_types::bin;
default:
@@ -11,9 +11,30 @@
namespace cldnn {
GPU_DEFINE_PRIMITIVE_TYPE_ID(convert_color)
layout convert_color_inst::calc_output_layout(convert_color_node const& node, kernel_impl_params const& impl_param) {
layout convert_color_inst::calc_output_layout(convert_color_node const& /* node */, kernel_impl_params const& impl_param) {
auto desc = impl_param.typed_desc<convert_color>();
return desc->output_layout;
auto src_fmt = desc->input_color_format;
auto dst_fmt = desc->output_color_format;
auto dst_is_rgb_or_bgr = dst_fmt == convert_color::color_format::BGR ||
dst_fmt == convert_color::color_format::RGB;
auto inputs_count = desc->input_size();
bool single_plane_input = inputs_count == 1;
const size_t h_dim = 1;
const size_t c_dim = 3;
if ((src_fmt == convert_color::color_format::NV12 || src_fmt == convert_color::color_format::I420) && dst_is_rgb_or_bgr) {
auto out_layout = impl_param.get_input_layout(0);
out_layout.format = format::bfyx;
auto out_shape = out_layout.get_partial_shape();
out_shape[c_dim] = 3;
if (single_plane_input) {
out_shape[h_dim] = out_shape[h_dim] * 2 / 3;
}
out_layout.set_partial_shape(out_shape);
return out_layout;
}
OPENVINO_THROW("[GPU] Unsupported color format combinations");
}
std::string convert_color_inst::to_string(convert_color_node const& node) {
+1 -1
View File
@@ -122,7 +122,7 @@ std::vector<layout> crop_inst::calc_output_layouts(const crop_node& /*node*/, co
// update split offsets
if (is_output_static) {
auto p_param = const_cast<kernel_impl_params*>(&impl_param);
InferenceEngine::SizeVector startOffset(p_param->input_layouts[0].get_partial_shape().size());
ov::Shape startOffset(p_param->input_layouts[0].get_partial_shape().size());
auto input_shape = p_param->input_layouts[0].get_partial_shape();
auto dims = p_param->input_layouts[0].get_partial_shape().size();
for (int32_t prev = 0; prev < desc->output_idx; prev++) {
@@ -54,9 +54,9 @@ attach_convert_color_impl::attach_convert_color_impl() {
std::make_tuple(data_types::f32, format::nv12),
std::make_tuple(data_types::f16, format::nv12),
std::make_tuple(data_types::u8, format::nv12),
std::make_tuple(data_types::f32, format::byxf),
std::make_tuple(data_types::f16, format::byxf),
std::make_tuple(data_types::u8, format::byxf),
std::make_tuple(data_types::f32, format::bfyx),
std::make_tuple(data_types::f16, format::bfyx),
std::make_tuple(data_types::u8, format::bfyx),
});
}
@@ -10,10 +10,10 @@
#include "intel_gpu/graph/serialization/binary_buffer.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/file_util.hpp"
#include "to_string_utils.h"
#include "register.hpp"
#include "utils.hpp"
#include "openvino/util/file_util.hpp"
#include "runtime/ocl/ocl_event.hpp"
#include "quantize_inst.h"
@@ -368,7 +368,7 @@ private:
{
std::lock_guard<std::mutex> lock(cacheAccessMutex);
ov::util::save_binary(generate_cache_path_from_key(config, key), cache);
ov::intel_gpu::save_binary(generate_cache_path_from_key(config, key), cache);
}
} else {
_prim = PrimType(_pd, cache);
+11 -5
View File
@@ -768,8 +768,7 @@ event::ptr network::set_input_data(const primitive_id& id, memory::ptr data) {
primitive_inst = find_primitive(id);
if (primitive_inst == nullptr)
throw std::runtime_error("topology doesn't contain primitive:" + id);
OPENVINO_ASSERT(primitive_inst != nullptr, "[GPU] topology doesn't contain primitive: ", id);
if (primitive_inst->type() != input_layout::type_id()) {
CLDNN_ERROR_MESSAGE(id, "primitive " + id + " is not an input");
@@ -911,8 +910,7 @@ std::vector<event::ptr> network::set_output_memory(const primitive_id& id, memor
std::vector<event::ptr> ret_ev;
p_inst = find_primitive(id);
if (!p_inst)
throw std::runtime_error("topology doesn't contain primitive: " + id);
OPENVINO_ASSERT(p_inst != nullptr, "[GPU] topology doesn't contain primitive: ", id);
auto iter = std::find(_outputs.begin(), _outputs.end(), p_inst);
if (iter == _outputs.end())
@@ -927,7 +925,11 @@ std::vector<event::ptr> network::set_output_memory(const primitive_id& id, memor
}
for (auto& prim : o_iter->second) {
ret_ev.push_back(prim->set_output_memory(eng.reinterpret_buffer(*mem_new, prim->output_memory().get_layout()), false));
auto mem = mem_new;
if (!prim->is_dynamic() && mem_new && prim->output_memory_ptr())
mem = eng.reinterpret_buffer(*mem_new, prim->output_memory().get_layout());
ret_ev.push_back(prim->set_output_memory(mem));
if (!_reset_arguments &&
(prim->type() != cldnn::data::type_id() && !(prim->type() == cldnn::mutable_data::type_id() && prim->dependencies().empty()))) {
prim->set_arguments();
@@ -1722,6 +1724,10 @@ void network::allocate_variables_memories() {
}
}
const cldnn::network::variables_state_info_map& network::get_variables_state_info() const {
return _variables_state_info;
}
void network::set_variables_state_info(const std::string& variable_id, const cldnn::layout& layout) {
auto it = _variables_state_info.find(variable_id);
if (it == _variables_state_info.end()) {
+5 -5
View File
@@ -2,14 +2,14 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/runtime/system_conf.hpp"
#include "intel_gpu/runtime/memory.hpp"
#include "intel_gpu/runtime/engine.hpp"
#include "intel_gpu/runtime/debug_configuration.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include "intel_gpu/graph/program.hpp"
#include <ie_system_conf.h>
#include "auto_tuner.h"
#include "layout_optimizer.h"
#include "pass_manager.h"
@@ -105,12 +105,12 @@ using namespace cldnn;
using namespace ov::intel_gpu;
static void adjust_num_cores(ov::threading::IStreamsExecutor::Config& config) {
if (InferenceEngine::getAvailableCoresTypes().size() == 1) {
if (ov::get_available_cores_types().size() == 1) {
return;
}
const auto total_num_cores = InferenceEngine::getNumberOfLogicalCPUCores();
const auto total_num_big_cores = InferenceEngine::getNumberOfLogicalCPUCores(true);
const auto total_num_cores = ov::get_number_of_logical_cpu_cores();
const auto total_num_big_cores = ov::get_number_of_logical_cpu_cores(true);
const auto total_num_little_cores = total_num_cores - total_num_big_cores;
auto core_type = config._threadPreferredCoreType;
@@ -117,7 +117,11 @@ std::unique_ptr<json_composite> program_node::desc_to_json() const {
s << get_preferred_impl_type();
node_info->add("preferred impl", s.str());
node_info->add("output layout", output_layouts[0].to_short_string());
json_composite output_layouts_desc;
for (size_t i = 0; i < output_layouts.size(); i++) {
output_layouts_desc.add(std::to_string(i), output_layouts[i].to_short_string());
}
node_info->add("output layouts", output_layouts_desc);
node_info->add("constant", bool_to_str(constant));
node_info->add("in data flow", bool_to_str(data_flow));
@@ -168,7 +172,9 @@ std::unique_ptr<json_composite> program_node::desc_to_json() const {
if (empty) {
empty = false;
}
deps_ptrs.push_back(std::to_string(reinterpret_cast<uintptr_t>(itr->first)));
auto ptr = std::to_string(reinterpret_cast<uintptr_t>(itr->first));
auto port = std::to_string(itr->second);
deps_ptrs.push_back(ptr + "(" + port + ")");
itr++;
}
if (deps_ptrs.empty()) {
+9 -3
View File
@@ -28,10 +28,16 @@ layout reorder_inst::calc_output_layout(reorder_node const& node, kernel_impl_pa
}
if (ifmt.is_nv12() && !desc->has_surface_input()) {
auto data_size = tensor{ input_layout.batch(), input_layout.feature() * 3,
input_layout.spatial(0), input_layout.spatial(1) };
const size_t h_dim = 1;
const size_t c_dim = 3;
auto out_shape = input_layout.get_partial_shape();
out_shape[c_dim] = 3;
if (desc->input_size() == 1)
out_shape[h_dim] = out_shape[h_dim] * 2 / 3;
if (ofmt != ifmt)
return layout(odt, ofmt, data_size, op);
return layout(out_shape, odt, ofmt, op);
CLDNN_ERROR_MESSAGE(desc->id, "No image_nv12 to image_nv12 reorder is supported");
} else if (ofmt.is_winograd() && ifmt.is_winograd()) {
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/unique.hpp"
#include <sstream>
#include <string>
@@ -4,6 +4,10 @@
#include "include/batch_headers/fetch_data.cl"
#define IMAGE_W INPUT0_SIZE_Y
#define IMAGE_H (INPUT0_FEATURE_NUM * 2 / 3)
#if defined(CONVERT_FROM_NV12) || defined(CONVERT_FROM_I420)
#ifdef BUFFER_MEM
KERNEL(convert_color_ref)(const __global INPUT0_TYPE* input1,
@@ -19,22 +23,22 @@ KERNEL(convert_color_ref)(const __global INPUT0_TYPE* input1,
const uint y = get_global_id(1);
const uint x = get_global_id(2);
float Y = input1[GET_DATA_INDEX(INPUT0, b, 0, y, x)];
float Y = input1[GET_DATA_INDEX(INPUT0, b, y, x, 0)];
#if INPUTS_COUNT == 3
float U = input2[GET_DATA_INDEX(INPUT1, b, 0, y / 2, x / 2)];
float V = input3[GET_DATA_INDEX(INPUT2, b, 0, y / 2, x / 2)];
float U = input2[GET_DATA_INDEX(INPUT1, b, y / 2, x / 2, 0)];
float V = input3[GET_DATA_INDEX(INPUT2, b, y / 2, x / 2, 0)];
#elif INPUTS_COUNT == 2
float U = input2[GET_DATA_INDEX(INPUT1, b, 0, y / 2, x / 2)];
float V = input2[GET_DATA_INDEX(INPUT1, b, 1, y / 2, x / 2)];
float U = input2[GET_DATA_INDEX(INPUT1, b, y / 2, x / 2, 0)];
float V = input2[GET_DATA_INDEX(INPUT1, b, y / 2, x / 2, 1)];
#else // Single plane
uint input_uv_offset = INPUT0_SIZE_X * INPUT0_SIZE_Y / 3 * 2;
uint input_uv_offset = IMAGE_W * IMAGE_H;
#ifdef CONVERT_FROM_NV12
float U = input1[GET_DATA_INDEX(INPUT0, b, 0, y / 2, (x / 2) * 2) + input_uv_offset];
float V = input1[GET_DATA_INDEX(INPUT0, b, 1, y / 2, (x / 2) * 2) + input_uv_offset];
float U = input1[GET_DATA_INDEX(INPUT0, b, (y / 2), (x / 2) * 2, 0) + input_uv_offset];
float V = input1[GET_DATA_INDEX(INPUT0, b, (y / 2), (x / 2) * 2, 0) + input_uv_offset + 1];
#else
float U = input1[GET_DATA_INDEX(INPUT0, b, 0, 0, x / 2 + (y / 2)*(INPUT0_Y_PITCH / 2)) + input_uv_offset];
float V = input1[GET_DATA_INDEX(INPUT0, b, 0, 0, x / 2 + (y / 2)*(INPUT0_Y_PITCH / 2)) + 5 * input_uv_offset / 4];
float U = input1[GET_DATA_INDEX(INPUT0, b, 0, x / 2 + (y / 2)*(INPUT0_FEATURE_PITCH / 2), 0) + input_uv_offset];
float V = input1[GET_DATA_INDEX(INPUT0, b, 0, x / 2 + (y / 2)*(INPUT0_FEATURE_PITCH / 2), 0) + 5 * input_uv_offset / 4];
#endif
#endif
@@ -53,13 +57,13 @@ KERNEL(convert_color_ref)(const __global INPUT0_TYPE* input1,
#endif
#ifdef CONVERT_TO_RGB
output[OUTPUT_GET_INDEX(b, 0, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 1, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 2, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 0)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 1)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 2)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
#else // BGR
output[OUTPUT_GET_INDEX(b, 0, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 1, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 2, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 0)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 1)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 2)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
#endif
}
#endif
@@ -92,9 +96,8 @@ KERNEL(convert_color_ref)(read_only image2d_t input1,
float Ucomponent = mad(UV.x, 255.0f, -128.f);
float Vcomponent = mad(UV.y, 255.0f, -128.f);
#else // Single plane
uint input_y_offset = INPUT0_SIZE_Y / 3 * 2;
float4 U = read_imagef(input1, (int2)((x / 2) * 2, y / 2 + input_y_offset));
float4 V = read_imagef(input1, (int2)((x / 2) * 2 + 1, y / 2 + input_y_offset));
float4 U = read_imagef(input1, (int2)((x / 2) * 2, y / 2 + IMAGE_H));
float4 V = read_imagef(input1, (int2)((x / 2) * 2 + 1, y / 2 + IMAGE_H));
float Ucomponent = mad(U.x, 255.0f, -128.f);
float Vcomponent = mad(V.x, 255.0f, -128.f);
#endif
@@ -110,13 +113,13 @@ KERNEL(convert_color_ref)(read_only image2d_t input1,
#endif
#ifdef CONVERT_TO_RGB
output[OUTPUT_GET_INDEX(b, 0, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 1, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 2, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 0)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 1)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 2)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
#else // BGR
output[OUTPUT_GET_INDEX(b, 0, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 1, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, 2, y, x)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 0)] = ACTIVATION(TO_OUTPUT_TYPE(B), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 1)] = ACTIVATION(TO_OUTPUT_TYPE(G), ACTIVATION_PARAMS);
output[OUTPUT_GET_INDEX(b, y, x, 2)] = ACTIVATION(TO_OUTPUT_TYPE(R), ACTIVATION_PARAMS);
#endif
}
#endif
@@ -86,7 +86,7 @@ KERNEL (reorder_data)(
#if defined INPUT0_LAYOUT_NV12 && !SURFACE_INPUT
const sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | CLK_FILTER_NEAREST | CLK_ADDRESS_CLAMP;
float4 colorVYU = read_imagef(input, sampler, (int2)(x, y));
float4 colorVYU = read_imagef(input, sampler, (int2)(y, f));
float Ycomponent = mad(colorVYU.s1, 296.82f, -18.624f);
float Ucomponent = mad(colorVYU.s2, 255.0f, -128.f);
@@ -128,7 +128,7 @@ KERNEL (reorder_data)(
res = MEAN_OP(res, mean_subtract[GET_DATA_INDEX_SAFE(MEAN_SUBTRACT, msv.s0, msv.s1, /*msv.s2, msv.s3, msv.s4,msv.s5,*/ msv.s6, msv.s7)]);
#endif
#elif SURFACE_INPUT
float4 Y = read_imagef(input, (int2)(x, y));
float4 Y = read_imagef(input, (int2)(y, f));
float Ycomponent = mad(Y.x, 296.82f, -18.624f);
float res = clamp(Ycomponent, 0.f, 255.f);
#else
@@ -156,6 +156,7 @@ std::string toString(WeightsType wType) {
case WeightsType::F16: return "F16";
case WeightsType::F32: return "F32";
case WeightsType::INT8: return "INT8";
case WeightsType::UINT8: return "UINT8";
default: return "";
}
}
@@ -28,7 +28,7 @@ CommonDispatchData ConvertColorKernelBase::SetDefault(const convert_color_params
auto in_layout = params.inputs[0].GetLayout();
auto out_layout = params.outputs[0].GetLayout();
dispatchData.gws = { out.Batch().v, out.Y().v, out.X().v };
dispatchData.gws = { out.Batch().v, out.Feature().v, out.Y().v };
dispatchData.lws = GetOptimalLocalWorkGroupSizes(dispatchData.gws, params.engineInfo, in_layout, out_layout);
return dispatchData;
@@ -19,8 +19,8 @@ ParamsKey ConvertColorKernelRef::GetSupportedKey() const {
k.EnableOutputDataType(Datatype::UINT8);
k.EnableInputLayout(DataLayout::nv12);
k.EnableInputLayout(DataLayout::byxf);
k.EnableOutputLayout(DataLayout::byxf);
k.EnableInputLayout(DataLayout::bfyx);
k.EnableOutputLayout(DataLayout::bfyx);
k.EnableDifferentTypes();
k.EnableTensorOffset();
@@ -9,40 +9,33 @@
namespace ov {
namespace intel_gpu {
AsyncInferRequest::AsyncInferRequest(const InferRequest::Ptr &inferRequest,
const InferenceEngine::ITaskExecutor::Ptr& taskExecutor,
const InferenceEngine::ITaskExecutor::Ptr& waitExecutor,
const InferenceEngine::ITaskExecutor::Ptr& callbackExecutor)
: AsyncInferRequestThreadSafeDefault(inferRequest, taskExecutor, callbackExecutor), _inferRequest(inferRequest), _waitExecutor(waitExecutor) {
_pipeline = {};
if (!_inferRequest->use_external_queue()) {
_pipeline.push_back({taskExecutor,
[this] {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "AsyncInferRequest::PreprocessingAndStartPipeline");
_inferRequest->setup_stream_graph();
_inferRequest->enqueue();
_inferRequest->wait();
} });
} else {
_pipeline.push_back({ _waitExecutor,
AsyncInferRequest::AsyncInferRequest(const std::shared_ptr<SyncInferRequest>& infer_request,
const std::shared_ptr<ov::threading::ITaskExecutor>& task_executor,
const std::shared_ptr<ov::threading::ITaskExecutor>& wait_executor,
const std::shared_ptr<ov::threading::ITaskExecutor>& callback_executor)
: ov::IAsyncInferRequest(infer_request, task_executor, callback_executor)
, m_infer_request(infer_request)
, m_wait_executor(wait_executor) {
m_infer_request->set_task_executor(task_executor);
if (infer_request->use_external_queue()) {
m_pipeline.clear();
m_pipeline.emplace_back(wait_executor,
[this] {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "AsyncInferRequest::WaitPipeline");
_inferRequest->wait_notify();
} });
m_infer_request->wait_notify();
});
}
}
void AsyncInferRequest::StartAsync_ThreadUnsafe() {
if (_inferRequest->use_external_queue()) {
_inferRequest->setup_stream_graph();
_inferRequest->enqueue_notify();
void AsyncInferRequest::start_async() {
if (m_infer_request->use_external_queue()) {
m_infer_request->setup_stream_graph();
m_infer_request->enqueue_notify();
}
Parent::StartAsync_ThreadUnsafe();
Parent::start_async();
}
AsyncInferRequest::~AsyncInferRequest() {
StopAndWait();
stop_and_wait();
}
} // namespace intel_gpu
@@ -1,51 +0,0 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "intel_gpu/plugin/async_infer_request_legacy.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include <memory>
namespace ov {
namespace intel_gpu {
AsyncInferRequestLegacy::AsyncInferRequestLegacy(const InferRequestLegacy::Ptr &inferRequest,
const InferenceEngine::ITaskExecutor::Ptr& taskExecutor,
const InferenceEngine::ITaskExecutor::Ptr& waitExecutor,
const InferenceEngine::ITaskExecutor::Ptr& callbackExecutor)
: AsyncInferRequestThreadSafeDefault(inferRequest, taskExecutor, callbackExecutor), _inferRequest(inferRequest), _waitExecutor(waitExecutor) {
_pipeline = {};
if (!_inferRequest->use_external_queue()) {
_pipeline.push_back({taskExecutor,
[this] {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "AsyncInferRequest::PreprocessingAndStartPipeline");
_inferRequest->setup_stream_graph();
_inferRequest->preprocess();
_inferRequest->enqueue();
_inferRequest->wait();
} });
} else {
_pipeline.push_back({ _waitExecutor,
[this] {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "AsyncInferRequest::WaitPipeline");
_inferRequest->wait_notify();
} });
}
}
void AsyncInferRequestLegacy::StartAsync_ThreadUnsafe() {
if (_inferRequest->use_external_queue()) {
_inferRequest->setup_stream_graph();
_inferRequest->preprocess_notify();
_inferRequest->enqueue_notify();
}
Parent::StartAsync_ThreadUnsafe();
}
AsyncInferRequestLegacy::~AsyncInferRequestLegacy() {
StopAndWait();
}
} // namespace intel_gpu
} // namespace ov
@@ -3,27 +3,22 @@
//
#include "intel_gpu/plugin/legacy_api_helper.hpp"
#include "intel_gpu/plugin/legacy_remote_context.hpp"
#include "openvino/pass/serialize.hpp"
#include "openvino/runtime/iplugin.hpp"
#include "openvino/runtime/intel_gpu/properties.hpp"
#include "openvino/util/common_util.hpp"
#include "intel_gpu/graph/serialization/binary_buffer.hpp"
#include "intel_gpu/graph/serialization/layout_serializer.hpp"
#include "intel_gpu/graph/serialization/string_serializer.hpp"
#include "intel_gpu/graph/serialization/utils.hpp"
#include "intel_gpu/graph/serialization/vector_serializer.hpp"
#include "intel_gpu/plugin/graph.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include "intel_gpu/plugin/infer_request.hpp"
#include "intel_gpu/plugin/graph.hpp"
#include "intel_gpu/plugin/compiled_model.hpp"
#include "intel_gpu/plugin/async_infer_request.hpp"
#include "intel_gpu/plugin/async_infer_request_legacy.hpp"
#include <threading/ie_executor_manager.hpp>
#include "threading/ie_cpu_streams_executor.hpp"
#include "cpp_interfaces/interface/ie_internal_plugin_config.hpp"
#include "cpp_interfaces/interface/ie_iinfer_request_internal.hpp"
#include "ie_icore.hpp"
#include <fstream>
#include <utility>
@@ -32,214 +27,175 @@
#include <cmath>
#include <algorithm>
#include <openvino/util/common_util.hpp>
using namespace InferenceEngine;
using namespace InferenceEngine::details;
namespace ov {
namespace intel_gpu {
CompiledModel::CompiledModel(InferenceEngine::CNNNetwork &network,
InferenceEngine::RemoteContext::Ptr context,
const ExecutionConfig& config,
InferenceEngine::InputsDataMap* inputs,
InferenceEngine::OutputsDataMap* outputs) :
InferenceEngine::ExecutableNetworkThreadSafeDefault{[&]() -> InferenceEngine::ITaskExecutor::Ptr {
if (config.get_property(ov::internal::exclusive_async_requests)) {
//exclusiveAsyncRequests essentially disables the streams (and hence should be checked first) => aligned with the CPU behavior
return executorManager()->getExecutor("GPU");
} else if (config.get_property(ov::num_streams) > 1) {
return std::make_shared<InferenceEngine::CPUStreamsExecutor>(
IStreamsExecutor::Config{"Intel GPU plugin executor", config.get_property(ov::num_streams)});
} else {
return std::make_shared<InferenceEngine::CPUStreamsExecutor>(
IStreamsExecutor::Config{"Intel GPU plugin executor", 1});
}
}()},
m_context(context),
m_config(config),
m_taskExecutor{ _taskExecutor },
m_waitExecutor(executorManager()->getIdleCPUStreamsExecutor({ "GPUWaitExecutor" })),
m_network(network) {
auto graph_base = std::make_shared<Graph>(network, get_context_impl(m_context), m_config, 0, inputs, outputs);
namespace {
std::shared_ptr<ov::threading::ITaskExecutor> create_task_executor(const std::shared_ptr<const ov::IPlugin>& plugin, const ExecutionConfig& config) {
if (config.get_property(ov::internal::exclusive_async_requests)) {
//exclusive_async_requests essentially disables the streams (and hence should be checked first) => aligned with the CPU behavior
return plugin->get_executor_manager()->get_executor("GPU");
} else {
return std::make_shared<ov::threading::CPUStreamsExecutor>(
ov::threading::IStreamsExecutor::Config{"Intel GPU plugin executor", config.get_property(ov::num_streams)});
}
}
} // namespace
CompiledModel::CompiledModel(std::shared_ptr<ov::Model> model,
const std::shared_ptr<const ov::IPlugin>& plugin,
RemoteContextImpl::Ptr context,
const ExecutionConfig& config)
: ov::ICompiledModel(model,
plugin,
wrap_if_old_api(context, plugin->is_new_api()),
create_task_executor(plugin, config))
, m_context(context)
, m_config(config)
, m_wait_executor(std::make_shared<ov::threading::CPUStreamsExecutor>(ov::threading::IStreamsExecutor::Config{"Intel GPU plugin wait executor"}))
, m_model(model->is_dynamic() ? model : nullptr)
, m_model_name(model->get_friendly_name())
, m_inputs(ov::ICompiledModel::inputs())
, m_outputs(ov::ICompiledModel::outputs())
, m_loaded_from_cache(false) {
auto graph_base = std::make_shared<Graph>(model, m_context, m_config, 0);
for (uint16_t n = 0; n < m_config.get_property(ov::num_streams); n++) {
auto graph = n == 0 ? graph_base : std::make_shared<Graph>(graph_base, n);
m_graphs.push_back(graph);
}
}
CompiledModel::CompiledModel(cldnn::BinaryInputBuffer& ib,
InferenceEngine::RemoteContext::Ptr context,
const ExecutionConfig& config,
InferenceEngine::InputsDataMap* inputs,
InferenceEngine::OutputsDataMap* outputs) :
InferenceEngine::ExecutableNetworkThreadSafeDefault{[&]() -> InferenceEngine::ITaskExecutor::Ptr {
if (config.get_property(ov::internal::exclusive_async_requests)) {
//exclusiveAsyncRequests essentially disables the streams (and hence should be checked first) => aligned with the CPU behavior
return executorManager()->getExecutor("GPU");
} else if (config.get_property(ov::num_streams) > 1) {
return std::make_shared<InferenceEngine::CPUStreamsExecutor>(
IStreamsExecutor::Config{"Intel GPU plugin executor", config.get_property(ov::num_streams)});
} else {
return std::make_shared<InferenceEngine::CPUStreamsExecutor>(
IStreamsExecutor::Config{"Intel GPU plugin executor", 1});
CompiledModel::CompiledModel(cldnn::BinaryInputBuffer ib,
const std::shared_ptr<const ov::IPlugin>& plugin,
RemoteContextImpl::Ptr context,
const ExecutionConfig& config)
: ov::ICompiledModel(nullptr,
plugin,
wrap_if_old_api(context, plugin->is_new_api()),
create_task_executor(plugin, config))
, m_context(context)
, m_config(config)
, m_wait_executor(std::make_shared<ov::threading::CPUStreamsExecutor>(ov::threading::IStreamsExecutor::Config{"Intel GPU plugin wait executor"}))
, m_model(nullptr)
, m_model_name("")
, m_loaded_from_cache(true) {
{
size_t num_params;
ib >> num_params;
for (size_t idx = 0; idx < num_params; ++idx) {
std::string param_name;
ib >> param_name;
ov::element::Type param_element_type;
std::string str_element_type;
ib >> str_element_type;
std::stringstream oss(str_element_type);
oss >> param_element_type;
ov::PartialShape param_shape;
ib >> param_shape;
std::unordered_set<std::string> param_names;
size_t num_names;
ib >> num_names;
for (size_t i = 0; i < num_names; ++i) {
std::string name;
ib >> name;
param_names.emplace(name);
}
auto new_param = std::make_shared<ov::op::v0::Parameter>(param_element_type, param_shape);
new_param->set_friendly_name(param_name);
new_param->set_element_type(param_element_type);
new_param->output(0).get_tensor().set_names(param_names);
new_param->validate_and_infer_types();
m_inputs.push_back(new_param->output(0));
}
}()},
m_context(context),
m_config(config),
m_taskExecutor{ _taskExecutor },
m_waitExecutor(executorManager()->getIdleCPUStreamsExecutor({ "GPUWaitExecutor" })) {
auto context_impl = get_context_impl(m_context);
}
{
size_t num_results;
ib >> num_results;
for (size_t idx = 0; idx < num_results; ++idx) {
ov::element::Type fake_element_type;
std::string str_element_type;
ib >> str_element_type;
std::stringstream oss(str_element_type);
oss >> fake_element_type;
ov::PartialShape fake_shape;
ib >> fake_shape;
std::string fake_name;
ib >> fake_name;
std::string param_name;
ib >> param_name;
std::unordered_set<std::string> param_names;
size_t num_names;
ib >> num_names;
for (size_t i = 0; i < num_names; ++i) {
std::string name;
ib >> name;
param_names.emplace(name);
}
auto fake_param = std::make_shared<ov::op::v0::Parameter>(fake_element_type, fake_shape);
fake_param->set_friendly_name(fake_name);
fake_param->validate_and_infer_types();
auto new_result = std::make_shared<ov::op::v0::Result>(fake_param);
new_result->set_friendly_name(param_name);
new_result->output(0).get_tensor().set_names(param_names);
new_result->validate_and_infer_types();
m_outputs.push_back(new_result->output(0));
}
}
auto pos = ib.tellg();
for (uint16_t n = 0; n < m_config.get_property(ov::num_streams); n++) {
ib.seekg(pos);
auto graph = std::make_shared<Graph>(ib, context_impl, m_config, n, inputs, outputs);
auto graph = std::make_shared<Graph>(ib, context, m_config, 0);
m_graphs.push_back(graph);
}
}
template <class T>
IInferRequestInternal::Ptr CompiledModel::GetInferRequestImpl(const std::vector<std::shared_ptr<const ov::Node>>& inputs,
const std::vector<std::shared_ptr<const ov::Node>>& outputs) {
auto ptr = std::make_shared<T>(inputs, outputs, std::static_pointer_cast<CompiledModel>(shared_from_this()));
if (m_config.get_property(ov::num_streams) > 1)
ptr->EnableStreams();
if (m_config.get_property(ov::enable_profiling))
ptr->EnableProfiling();
if (m_graphs.front()->use_external_queue())
ptr->enable_external_queue();
ptr->SetGraph(m_graphs.front());
return ptr;
}
IInferRequestInternal::Ptr CompiledModel::CreateInferRequestImpl(InputsDataMap networkInputs,
OutputsDataMap networkOutputs) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "CompiledModel::CreateInferRequestImpl");
auto ptr = std::make_shared<InferRequestLegacy>(networkInputs, networkOutputs,
std::static_pointer_cast<CompiledModel>(shared_from_this()));
if (m_config.get_property(ov::num_streams) > 1)
ptr->EnableStreams();
if (m_config.get_property(ov::enable_profiling))
ptr->EnableProfiling();
if (m_graphs.front()->use_external_queue())
ptr->enable_external_queue();
ptr->SetGraph(m_graphs.front());
return ptr;
}
IInferRequestInternal::Ptr CompiledModel::CreateInferRequestImpl(const std::vector<std::shared_ptr<const ov::Node>>& inputs,
const std::vector<std::shared_ptr<const ov::Node>>& outputs) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "CompiledModel::CreateInferRequestImpl");
if (m_graphs.front()->GetMaxDynamicBatchSize() > 1)
return GetInferRequestImpl<InferRequestLegacy>(inputs, outputs);
else
return GetInferRequestImpl<InferRequest>(inputs, outputs);
}
IInferRequestInternal::Ptr CompiledModel::CreateInferRequest() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "CompiledModel::CreateInferRequest");
InferenceEngine::IInferRequestInternal::Ptr internalRequest;
if (m_graphs.empty()) {
OPENVINO_THROW("[GPU] Model not loaded");
}
for (auto& graph : m_graphs) {
if (graph == nullptr) {
OPENVINO_THROW("[GPU] Model not loaded");
}
if (!graph->IsLoaded()) {
OPENVINO_THROW("[GPU] Model not loaded: no networks created");
}
}
bool is_legacy = false;
if (this->_plugin && _plugin->IsNewAPI()) {
internalRequest = CreateInferRequestImpl(_parameters, _results);
if (std::dynamic_pointer_cast<InferRequestLegacy>(internalRequest))
is_legacy = true;
}
if (!internalRequest) {
internalRequest = CreateInferRequestImpl(_networkInputs, _networkOutputs);
is_legacy = true;
}
internalRequest->setPointerToExecutableNetworkInternal(shared_from_this());
if (is_legacy) {
return std::make_shared<AsyncInferRequestLegacy>(std::static_pointer_cast<InferRequestLegacy>(internalRequest),
m_taskExecutor,
m_waitExecutor,
_callbackExecutor);
}
return std::make_shared<AsyncInferRequest>(std::static_pointer_cast<InferRequest>(internalRequest),
m_taskExecutor,
m_waitExecutor,
_callbackExecutor);
std::shared_ptr<ov::IAsyncInferRequest> CompiledModel::create_infer_request() const {
auto sync_request = create_sync_infer_request();
auto async_infer_request = std::make_shared<AsyncInferRequest>(std::static_pointer_cast<SyncInferRequest>(sync_request),
get_task_executor(),
m_wait_executor,
get_callback_executor());
return async_infer_request;
}
// Cache blob format:
// [ ConstInputsDataMap / ConstOutputsDataMap ]
// [ is_dynamic flag ]
// [ ov::Node::Input/ ov::Node::Output ]
// [ ov::intel_gpu::Graph ]
void CompiledModel::Export(std::ostream& networkModel) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "CompiledModel::Export");
if (m_graphs.empty())
OPENVINO_THROW("[GPU] Model not loaded");
void CompiledModel::export_model(std::ostream& model) const {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "CompiledModel::export_model");
OPENVINO_ASSERT(!m_graphs.empty(), "[GPU] Model not loaded");
cldnn::BinaryOutputBuffer ob(networkModel);
cldnn::BinaryOutputBuffer ob(model);
// InputsInfo and OutputsInfo for CNNNetwork
{
ob << GetInputsInfo().size();
for (const auto& in : GetInputsInfo()) {
ob << in.first;
std::string precision(in.second->getPrecision().name());
ob << precision;
std::stringstream ss;
ss << in.second->getInputData()->getLayout();
ob << ss.str();
ob << in.second->getTensorDesc().getDims();
}
ob << GetOutputsInfo().size();
for (const auto& out : GetOutputsInfo()) {
ob << out.first;
std::string precision(out.second->getPrecision().name());
ob << precision;
std::stringstream ss;
ss << out.second->getLayout();
ob << ss.str();
ob << out.second->getTensorDesc().getDims();
}
}
bool is_dynamic = get_graph(0)->get_network()->is_dynamic();
ob << is_dynamic;
// Inputs
{
const std::vector<std::shared_ptr<const ov::Node>>& const_params = getInputs();
ob << const_params.size();
const auto& params = inputs();
ob << params.size();
for (const auto& param : const_params) {
auto new_param = ov::as_type_ptr<const ov::op::v0::Parameter>(param);
ov::element::Type param_element_type = new_param->get_element_type();
const std::string& param_name = new_param->get_friendly_name();
const ov::PartialShape& param_shape = new_param->get_partial_shape();
const ov::Layout& param_layout = new_param->get_layout();
const auto& param_names = new_param->output(0).get_tensor().get_names();
ob << param_name;
for (const auto& param : params) {
std::stringstream ss;
ss << param_element_type;
ss << param.get_element_type();
ob << param.get_node()->get_friendly_name();
ob << ss.str();
ob << param_shape;
ob << param_layout.to_string();
ob << param_names.size();
for (const auto& name : param_names) {
ob << param.get_partial_shape();
ob << param.get_names().size();
for (const auto& name : param.get_names()) {
ob << name;
}
}
@@ -247,66 +203,44 @@ void CompiledModel::Export(std::ostream& networkModel) {
// Outputs
{
std::vector<std::shared_ptr<const ov::Node>> const_results = getOutputs();
ob << const_results.size();
for (const auto& param : const_results) {
auto new_param = ov::as_type_ptr<const ov::op::v0::Result>(param);
ov::element::Type fake_element_type = new_param->get_input_element_type(0);
const std::string& fake_name = new_param->get_input_node_ptr(0)->get_friendly_name();
const std::string& param_name = new_param->get_friendly_name();
const ov::PartialShape& fake_shape = new_param->get_input_partial_shape(0);
const ov::Layout& param_layout = new_param->get_layout();
const auto& param_names = new_param->output(0).get_tensor().get_names();
const auto& results = outputs();
ob << results.size();
for (const auto& param : results) {
std::stringstream ss;
ss << fake_element_type;
ss << param.get_element_type();
ob << ss.str();
ob << fake_shape;
ob << fake_name;
ob << param_name;
ob << param_layout.to_string();
ob << param_names.size();
for (const auto& name : param_names) {
ob << param.get_partial_shape();
ob << param.get_node()->get_input_node_ptr(0)->get_friendly_name();
ob << param.get_node()->get_friendly_name();
ob << param.get_names().size();
for (const auto& name : param.get_names()) {
ob << name;
}
}
}
if (m_graphs.front()->GetNetwork()->is_dynamic()) {
ob << true;
ov::pass::StreamSerialize serializer(networkModel, {}, ov::pass::Serialize::Version::UNSPECIFIED);
serializer.run_on_model(std::const_pointer_cast<ngraph::Function>(m_network.getFunction()));
if (is_dynamic) {
ov::pass::StreamSerialize serializer(model, {}, ov::pass::Serialize::Version::UNSPECIFIED);
serializer.run_on_model(m_model);
} else {
ob << false;
m_graphs.front()->Export(ob);
get_graph(0)->export_model(ob);
}
}
std::shared_ptr<ngraph::Function> CompiledModel::GetExecGraphInfo() {
if (m_graphs.empty())
OPENVINO_THROW("[GPU] Model not loaded");
return m_graphs.front()->GetExecGraphInfo();
std::shared_ptr<const ov::Model> CompiledModel::get_runtime_model() const {
return get_graph(0)->get_runtime_model();
}
const std::vector<std::shared_ptr<Graph>>& CompiledModel::get_graphs() const {
return m_graphs;
}
std::shared_ptr<Graph> CompiledModel::get_graph(size_t n) const {
OPENVINO_ASSERT(m_graphs.size() >= n, "[GPU] Invalid graph idx: ", n, ". Only ", m_graphs.size(), " were created");
return m_graphs[n];
}
InferenceEngine::Parameter CompiledModel::GetConfig(const std::string &name) const {
auto actual_name = name;
if (LegacyAPIHelper::is_legacy_property({name, nullptr}, _plugin->IsNewAPI())) {
actual_name = LegacyAPIHelper::convert_legacy_property({name, nullptr}).first;
}
auto val = m_config.get_property(actual_name);
if (LegacyAPIHelper::is_legacy_property({name, nullptr}, _plugin->IsNewAPI())) {
val = LegacyAPIHelper::convert_to_legacy_property({actual_name, val}).second;
}
return val;
}
InferenceEngine::Parameter CompiledModel::GetMetric(const std::string &name) const {
ov::Any CompiledModel::get_property(const std::string& name) const {
if (name == ov::supported_properties) {
return decltype(ov::supported_properties)::value_type {
// Metrics
@@ -333,17 +267,20 @@ InferenceEngine::Parameter CompiledModel::GetMetric(const std::string &name) con
ov::PropertyName{ov::execution_devices.name(), PropertyMutability::RO}
};
} else if (name == ov::model_name) {
OPENVINO_ASSERT(!m_graphs.empty());
return decltype(ov::model_name)::value_type {m_graphs[0]->getName()};
return decltype(ov::model_name)::value_type {m_model_name};
} else if (name == ov::loaded_from_cache) {
return decltype(ov::loaded_from_cache)::value_type {m_loaded_from_cache};
OPENVINO_SUPPRESS_DEPRECATED_START
} else if (name == METRIC_KEY(SUPPORTED_METRICS)) {
std::vector<std::string> metrics;
metrics.push_back(METRIC_KEY(NETWORK_NAME));
metrics.push_back(METRIC_KEY(SUPPORTED_METRICS));
metrics.push_back(METRIC_KEY(SUPPORTED_CONFIG_KEYS));
metrics.push_back(METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS));
static const std::vector<std::string> metrics {
METRIC_KEY(NETWORK_NAME),
METRIC_KEY(SUPPORTED_METRICS),
METRIC_KEY(SUPPORTED_CONFIG_KEYS),
METRIC_KEY(OPTIMAL_NUMBER_OF_INFER_REQUESTS),
};
IE_SET_METRIC_RETURN(SUPPORTED_METRICS, metrics);
} else if (name == METRIC_KEY(SUPPORTED_CONFIG_KEYS)) {
static const std::vector<std::string> configKeys {
static const std::vector<std::string> config_keys {
CONFIG_KEY(MODEL_PRIORITY),
CONFIG_KEY(PERFORMANCE_HINT),
CONFIG_KEY(PERFORMANCE_HINT_NUM_REQUESTS),
@@ -360,21 +297,40 @@ InferenceEngine::Parameter CompiledModel::GetMetric(const std::string &name) con
GPU_CONFIG_KEY(MAX_NUM_THREADS),
GPU_CONFIG_KEY(ENABLE_LOOP_UNROLLING),
};
IE_SET_METRIC_RETURN(SUPPORTED_CONFIG_KEYS, configKeys);
IE_SET_METRIC_RETURN(SUPPORTED_CONFIG_KEYS, config_keys);
OPENVINO_SUPPRESS_DEPRECATED_END
} else if (name == ov::optimal_number_of_infer_requests) {
unsigned int nr = m_config.get_property(ov::num_streams);
if (m_config.get_property(ov::hint::performance_mode) != ov::hint::PerformanceMode::LATENCY)
nr *= 2;
return decltype(ov::optimal_number_of_infer_requests)::value_type {nr};
} else if (name == ov::execution_devices) {
return decltype(ov::execution_devices)::value_type{m_context->getDeviceName()};
} else {
OPENVINO_THROW("[GPU] Unsupported CompiledModel property: ", name);
return decltype(ov::execution_devices)::value_type{m_context->get_device_name()};
}
auto actual_name = name;
if (LegacyAPIHelper::is_legacy_property({name, nullptr}, is_new_api())) {
actual_name = LegacyAPIHelper::convert_legacy_property({name, nullptr}).first;
}
auto val = m_config.get_property(actual_name);
if (LegacyAPIHelper::is_legacy_property({name, nullptr}, is_new_api())) {
val = LegacyAPIHelper::convert_to_legacy_property({actual_name, val}).second;
}
return val;
}
std::shared_ptr<InferenceEngine::RemoteContext> CompiledModel::GetContext() const {
return m_context;
std::shared_ptr<ov::ISyncInferRequest> CompiledModel::create_sync_infer_request() const {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "CompiledModel::create_sync_infer_request");
OPENVINO_ASSERT(!m_graphs.empty(), "[GPU] Model not loaded");
for (auto& graph : m_graphs) {
OPENVINO_ASSERT(graph != nullptr, "[GPU] Model not loaded: graph is nullptr");
OPENVINO_ASSERT(graph->is_loaded(), "[GPU] Model not loaded: invalid graph");
}
return std::make_shared<SyncInferRequest>(std::static_pointer_cast<const CompiledModel>(shared_from_this()));
}
} // namespace intel_gpu
+117 -230
View File
@@ -2,6 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "intel_gpu/runtime/layout.hpp"
#include "openvino/runtime/threading/executor_manager.hpp"
#include "openvino/runtime/exec_model_info.hpp"
#include "openvino/pass/serialize.hpp"
#include "intel_gpu/graph/network.hpp"
#include "intel_gpu/graph/serialization/binary_buffer.hpp"
#include "intel_gpu/graph/serialization/map_serializer.hpp"
@@ -14,10 +19,6 @@
#include "intel_gpu/runtime/itt.hpp"
#include "intel_gpu/plugin/graph.hpp"
#include "intel_gpu/plugin/simple_math.hpp"
#include "intel_gpu/plugin/infer_request.hpp"
#include "openvino/runtime/threading/executor_manager.hpp"
#include "openvino/runtime/exec_model_info.hpp"
#include <list>
#include <set>
@@ -31,36 +32,29 @@
#include <sys/types.h>
#include <sys/stat.h>
using namespace InferenceEngine;
using namespace InferenceEngine::details;
namespace ov {
namespace intel_gpu {
Graph::Graph(InferenceEngine::CNNNetwork& network, const RemoteContextImpl::Ptr& context, const ExecutionConfig& config, uint16_t stream_id,
InferenceEngine::InputsDataMap* inputs, InferenceEngine::OutputsDataMap* outputs)
Graph::Graph(std::shared_ptr<ov::Model> model, const RemoteContextImpl::Ptr& context, const ExecutionConfig& config, uint16_t stream_id)
: m_context(context)
, m_networkName(network.getName())
, m_config(config)
, m_stream_id(stream_id)
, m_state(0) {
m_program = std::make_shared<ProgramBuilder>(network, get_engine(), config, false, false, inputs, outputs);
if (m_program->m_max_batch > 1)
m_config.set_property(ov::intel_gpu::max_dynamic_batch(m_program->m_max_batch));
Build();
, m_stream_id(stream_id) {
auto program_builder = std::make_shared<ProgramBuilder>(model, get_engine(), config, false, false);
m_config = program_builder->get_config();
build(program_builder->get_compiled_program());
primitiveIDs = program_builder->primitive_ids;
prevPrimitiveIDs = program_builder->prevPrimitiveIDs;
profilingIDs = program_builder->profiling_ids;
perfMap = program_builder->perfMap;
m_input_layouts = program_builder->get_input_layouts();
}
Graph::Graph(cldnn::BinaryInputBuffer &ib, const RemoteContextImpl::Ptr& context, const ExecutionConfig& config, uint16_t stream_id,
InferenceEngine::InputsDataMap* inputs, InferenceEngine::OutputsDataMap* outputs)
Graph::Graph(cldnn::BinaryInputBuffer &ib, const RemoteContextImpl::Ptr& context, const ExecutionConfig& config, uint16_t stream_id)
: m_context(context)
, m_config(config)
, m_stream_id(stream_id)
, m_state(0) {
m_program = std::make_shared<ProgramBuilder>(get_engine(), config, inputs, outputs);
ib >> m_program->m_max_batch;
if (m_program->m_max_batch > 1)
m_config.set_property(ov::intel_gpu::max_dynamic_batch(m_program->m_max_batch));
, m_stream_id(stream_id) {
bool need_onednn_engine = false;
ib >> need_onednn_engine;
if (need_onednn_engine) {
@@ -71,12 +65,7 @@ Graph::Graph(cldnn::BinaryInputBuffer &ib, const RemoteContextImpl::Ptr& context
#endif // ENABLE_ONEDNN_FOR_GPU
}
ib >> m_program->inputLayouts;
ProgramBuilder::variables_state_info_map variablesStateInfoMap;
ib >> variablesStateInfoMap;
for (const auto& variablesStateInfo : variablesStateInfoMap) {
m_program->AddVariableStateInfo(variablesStateInfo.first, *variablesStateInfo.second.begin());
}
ib >> m_input_layouts;
ib >> primitiveIDs;
ib >> prevPrimitiveIDs;
ib >> profilingIDs;
@@ -89,71 +78,53 @@ Graph::Graph(cldnn::BinaryInputBuffer &ib, const RemoteContextImpl::Ptr& context
perfMap[prim_id].first = prim_id;
auto& perfEntry = perfMap[prim_id].second;
ib >> perfEntry.layerType;
ib >> cldnn::make_data(&perfEntry.status, sizeof(InferenceEngine::InferenceEngineProfileInfo::LayerStatus));
ib >> cldnn::make_data(&perfEntry.status, sizeof(ov::ProfilingInfo::Status));
perfEntry.cpu_uSec = perfEntry.realTime_uSec = 0;
ib >> perfEntry.isCPU;
ib >> perfEntry.parentPrimitive;
}
}
ib >> outputDims;
size_t num_networks;
ib >> num_networks;
for (uint32_t i = 0; i < num_networks; ++i) {
m_networks.emplace_back(std::make_shared<cldnn::network>(ib, get_engine().create_stream(config), get_engine(), m_stream_id == 0, i));
}
m_network = std::make_shared<cldnn::network>(ib, get_engine().create_stream(config), get_engine(), m_stream_id == 0, 0);
}
Graph::Graph(std::shared_ptr<Graph> graph, uint16_t stream_id)
: m_context(graph->m_context)
, m_program(graph->m_program)
, m_networkName(graph->m_networkName)
, m_config(graph->m_config)
, m_stream_id(stream_id)
, m_state(0) {
Build();
, primitiveIDs(graph->primitiveIDs)
, prevPrimitiveIDs(graph->prevPrimitiveIDs)
, perfMap(graph->perfMap)
, profilingIDs(graph->profilingIDs)
, m_input_layouts(graph->m_input_layouts) {
build(graph->get_network()->get_program());
}
void Graph::UpdateLayersMaps() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::UpdateLayersMaps");
primitiveIDs = m_program->primitive_ids;
prevPrimitiveIDs = m_program->prevPrimitiveIDs;
profilingIDs = m_program->profiling_ids;
perfMap = m_program->perfMap;
outputDims = m_program->outputDims;
}
void Graph::build(std::shared_ptr<cldnn::program> program) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::build");
void Graph::Build() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::Build");
UpdateLayersMaps();
if (GetMaxDynamicBatchSize() > 1) {
int m_bv_sz = m_program->GetMaxBatchSizeForSingleProgram();
for (int b = m_bv_sz - 1; b >= 0; b--) {
auto network = BuildNetwork(m_program->GetCompiledProgram(b));
m_networks.insert(m_networks.begin(), network);
}
auto external_queue = m_context->get_external_queue();
if (external_queue) {
OPENVINO_ASSERT(m_config.get_property(ov::num_streams) == 1, "[GPU] Throughput streams can't be used with shared queue!");
const auto &engine = program->get_engine();
m_network = std::make_shared<cldnn::network>(program, engine.create_stream(m_config, external_queue), m_stream_id);
} else {
auto network = BuildNetwork(m_program->GetCompiledProgram());
m_networks.emplace_back(network);
m_network = std::make_shared<cldnn::network>(program, m_stream_id);
}
GPU_DEBUG_GET_INSTANCE(debug_config);
GPU_DEBUG_IF(!debug_config->dry_run_path.empty()) {
CNNNetwork net(GetExecGraphInfo());
net.serialize(debug_config->dry_run_path);
ov::pass::Serialize(debug_config->dry_run_path, "").run_on_model(get_runtime_model());
exit(0);
}
GPU_DEBUG_IF(!debug_config->dump_graphs.empty() && m_stream_id == 0) {
static int net_id = 0;
auto steps_info = GetNetwork()->get_optimizer_passes_info();
auto steps_info = get_network()->get_optimizer_passes_info();
size_t step_idx = 0;
for (auto& step : steps_info) {
CNNNetwork net(GetExecGraphInfoByPrimitivesInfo(step.second, true));
net.serialize(debug_config->dump_graphs + std::to_string(net_id) + "_" +
std::to_string(step_idx) + "_" + step.first + "_graph.xml");
auto xml_path = debug_config->dump_graphs + std::to_string(net_id) + "_" + std::to_string(step_idx) + "_" + step.first + "_graph.xml";
ov::pass::Serialize(xml_path, "").run_on_model(get_runtime_model(step.second, true));
step_idx++;
}
net_id++;
@@ -164,73 +135,24 @@ bool Graph::use_external_queue() const {
return m_context->get_external_queue() != nullptr;
}
std::shared_ptr<cldnn::network> Graph::BuildNetwork(std::shared_ptr<cldnn::program> program) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::BuildNetwork");
std::shared_ptr<cldnn::network> network = nullptr;
auto externalQueue = m_context->get_external_queue();
if (externalQueue) {
if (m_config.get_property(ov::num_streams) != 1)
OPENVINO_THROW("Throughput streams can't be used with shared queue!\n");
auto &engine = m_program->get_engine();
network = std::make_shared<cldnn::network>(program, engine.create_stream(m_config, externalQueue), m_stream_id);
} else {
network = std::make_shared<cldnn::network>(program, m_stream_id);
}
return network;
}
Graph::variable_states_map Graph::AllocateVariablesMemories() {
Graph::variable_states_map states {};
const auto& memStatesInfo = m_program->GetVariablesStatesInfo();
OPENVINO_ASSERT(memStatesInfo.empty() || !GetNetwork()->is_dynamic(), "[GPU] Dynamic shapes are not supported yet for stateful models");
for (const auto& memStateInfo : memStatesInfo) {
std::vector<cldnn::layout> orderedLayouts {memStateInfo.second.begin(), memStateInfo.second.end()};
std::sort(orderedLayouts.begin(), orderedLayouts.end(), [](cldnn::layout& first, cldnn::layout& second) {
return first.batch() < second.batch();
});
std::vector<cldnn::network::VariableState::Ptr> memoryStates;
memoryStates.reserve(orderedLayouts.size());
for (const auto& layout : orderedLayouts)
memoryStates.push_back(std::make_shared<cldnn::network::VariableState>(get_engine().allocate_memory(layout, false)));
states.insert({memStateInfo.first, memoryStates });
}
return states;
}
std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::vector<cldnn::primitive_info>& primitives_info,
bool filter_const_primitives) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::GetExecGraphInfoByPrimitivesInfo");
std::shared_ptr<ov::Model> Graph::get_runtime_model(std::vector<cldnn::primitive_info>& primitives_info, bool filter_const_primitives) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::get_runtime_model");
if (m_config.get_property(ov::enable_profiling)) {
try {
// Update may throw an exception for step-by-step runtime graph dump,
// since network->get_executed_primitives() method can't be called before network execution
UpdatePerfStatistics();
update_profiling_info();
} catch (std::exception&) {
}
}
std::map<std::string, std::shared_ptr<ngraph::Node>> node2layer;
std::map<std::string, std::shared_ptr<ov::Node>> node2layer;
ngraph::ResultVector results;
ngraph::ParameterVector params;
ngraph::NodeVector nodes;
ov::ResultVector results;
ov::ParameterVector params;
ov::NodeVector nodes;
auto data_type_to_precision = [](cldnn::data_types dt) {
switch (dt) {
case cldnn::data_types::bin: return Precision::BIN;
case cldnn::data_types::f32: return Precision::FP32;
case cldnn::data_types::f16: return Precision::FP16;
case cldnn::data_types::i32: return Precision::I32;
case cldnn::data_types::i64: return Precision::I64;
case cldnn::data_types::u8: return Precision::U8;
case cldnn::data_types::i8: return Precision::I8;
default: return Precision::UNSPECIFIED;
}
};
// TODO: Adjust output layer names to be aligned with ngraph and add new ops
// TODO: Adjust output layer names to be aligned with ov and add new ops
auto to_IE_type_name = [](const std::string& cldnn_name) -> std::string{
static std::map<std::string, std::string> type_n2l {
{ "activation", "Activation" },
@@ -319,7 +241,7 @@ std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::v
return std::string((it+1), name.end());
};
auto extIdMap = GetNetwork()->get_ext_id_mapping();
auto extIdMap = get_network()->get_ext_id_mapping();
auto find_origin_layers = [&](const std::string& name) -> std::vector<std::string> {
if (extIdMap.find(name) == extIdMap.end()) {
@@ -329,7 +251,7 @@ std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::v
};
auto get_inputs = [&] (const cldnn::primitive_info& prim_info) {
ngraph::OutputVector inputs;
ov::OutputVector inputs;
auto& deps = prim_info.c_dependencies;
@@ -355,21 +277,21 @@ std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::v
return inputs;
};
auto create_ngraph_node = [&](const cldnn::primitive_info& prim_info) {
auto create_ov_node = [&](const cldnn::primitive_info& prim_info) {
const auto& user_ids = prim_info.c_users;
size_t output_size = user_ids.size();
bool is_output = user_ids.empty();
auto out_et = cldnn::data_type_to_element_type(prim_info.output_layout.data_type);
auto out_pshape = prim_info.output_layout.get_partial_shape();
std::shared_ptr<ngraph::Node> return_node;
std::shared_ptr<ov::Node> return_node;
if (prim_info.type_id == "input_layout") {
auto param = std::make_shared<ngraph::op::Parameter>(out_et, out_pshape);
auto param = std::make_shared<ov::op::v0::Parameter>(out_et, out_pshape);
params.push_back(param);
return_node = param;
// create additional result node if parameter is output without post reorder
if (is_output) {
results.emplace_back(std::make_shared<ngraph::op::Result>(return_node->get_default_output()));
results.emplace_back(std::make_shared<ov::op::v0::Result>(return_node->get_default_output()));
}
} else {
return_node = std::make_shared<ov::exec_model_info::ExecutionNode>(get_inputs(prim_info), output_size);
@@ -378,7 +300,7 @@ std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::v
nodes.push_back(return_node);
node2layer[prim_info.original_id] = return_node;
return_node->set_output_type(0, out_et, out_pshape);
results.emplace_back(std::make_shared<ngraph::op::Result>(return_node->get_default_output()));
results.emplace_back(std::make_shared<ov::op::v0::Result>(return_node->get_default_output()));
} else {
size_t port = 0;
for (auto& usr_id : user_ids) {
@@ -400,14 +322,12 @@ std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::v
results.back()->set_friendly_name(layerName + "_result");
std::map<std::string, std::string> info;
Precision prec = data_type_to_precision(prim_info.output_layout.data_type);
Precision inference_precision = data_type_to_precision(prim_info.runtime_precision);
info[ov::exec_model_info::OUTPUT_PRECISIONS] = prec.name();
info[ov::exec_model_info::OUTPUT_PRECISIONS] = cldnn::data_type_to_element_type(prim_info.output_layout.data_type).get_type_name();
info[ov::exec_model_info::LAYER_TYPE] = to_IE_type_name(prim_info.type_id);
info[ov::exec_model_info::OUTPUT_LAYOUTS] = prim_info.layout_str;
info[ov::exec_model_info::EXECUTION_ORDER] = std::to_string(prim_info.exec_id);
info[ov::exec_model_info::IMPL_TYPE] = prim_info.kernel_id;
info[ov::exec_model_info::RUNTIME_PRECISION] = inference_precision.name();
info[ov::exec_model_info::RUNTIME_PRECISION] = cldnn::data_type_to_element_type(prim_info.runtime_precision).get_type_name();
std::vector<std::string> originalNames{find_origin_layers(prim_info.original_id)};
for (auto& fused_id : prim_info.c_fused_ids) {
@@ -493,20 +413,17 @@ std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfoByPrimitivesInfo(std::v
}
}
create_ngraph_node(pi);
create_ov_node(pi);
}
return std::make_shared<ngraph::Function>(results, params, "runtime_gpu_graph");
return std::make_shared<ov::Model>(results, params, "runtime_gpu_graph");
}
// Cache blob format:
// [ ov::intel_gpu::ProgramBuilder::inputLayouts ]
// [ ov::intel_gpu::Graph::primitiveIDs ]
// [ ov::intel_gpu::Graph::outputDims ]
// [ cldnn::network ]
void Graph::Export(cldnn::BinaryOutputBuffer &ob) {
ob << m_program->m_max_batch;
void Graph::export_model(cldnn::BinaryOutputBuffer &ob) {
bool need_onednn_engine = false;
#ifdef ENABLE_ONEDNN_FOR_GPU
try {
@@ -518,8 +435,7 @@ void Graph::Export(cldnn::BinaryOutputBuffer &ob) {
#endif // ENABLE_ONEDNN_FOR_GPU
ob << need_onednn_engine;
ob << m_program->inputLayouts;
ob << m_program->GetVariablesStatesInfo();
ob << m_input_layouts;
ob << primitiveIDs;
ob << prevPrimitiveIDs;
ob << profilingIDs;
@@ -528,31 +444,23 @@ void Graph::Export(cldnn::BinaryOutputBuffer &ob) {
for (auto& perf_item : perfMap) {
ob << perf_item.first;
ob << perf_item.second.second.layerType;
ob << cldnn::make_data(&perf_item.second.second.status, sizeof(InferenceEngine::InferenceEngineProfileInfo::LayerStatus));
ob << cldnn::make_data(&perf_item.second.second.status, sizeof(ov::ProfilingInfo::Status));
ob << perf_item.second.second.isCPU;
ob << perf_item.second.second.parentPrimitive;
}
}
ob << outputDims;
ob << m_networks.size();
for (const auto& net : m_networks) {
net->save(ob);
}
m_network->save(ob);
}
std::shared_ptr<ngraph::Function> Graph::GetExecGraphInfo() {
auto primitives_info = GetNetwork()->get_primitives_info();
return GetExecGraphInfoByPrimitivesInfo(primitives_info, true);
std::shared_ptr<ov::Model> Graph::get_runtime_model() {
auto primitives_info = get_network()->get_primitives_info();
return get_runtime_model(primitives_info, true);
}
void Graph::UpdatePerfStatistics() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::UpdatePerfStatistics");
if (GetNetworksCount() == 0) {
return;
}
void Graph::update_profiling_info() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::update_profiling_info");
// Collect timings
auto collectTimings = [](cldnn::instrumentation::profiling_info& cldnnInfo, PerfCounter& pc) {
for (auto &interval : cldnnInfo.intervals) {
@@ -572,8 +480,8 @@ void Graph::UpdatePerfStatistics() {
}
};
std::map<cldnn::primitive_id, cldnn::event::ptr> executedPrimitives = GetNetwork()->get_executed_primitives();
auto allPrimitives = GetNetwork()->get_all_primitives();
std::map<cldnn::primitive_id, cldnn::event::ptr> executedPrimitives = get_network()->get_executed_primitives();
auto allPrimitives = get_network()->get_all_primitives();
// Get profiling info for all layers
for (auto &profiledID : profilingIDs) {
@@ -586,7 +494,7 @@ void Graph::UpdatePerfStatistics() {
// Change status if layer wasn't executed by cldnn engine
if (execIter == executedPrimitives.end()) {
if (perfCount.num == 0) {
perfCount.status = InferenceEngineProfileInfo::OPTIMIZED_OUT;
perfCount.status = ov::ProfilingInfo::Status::OPTIMIZED_OUT;
}
continue;
}
@@ -615,22 +523,21 @@ void Graph::UpdatePerfStatistics() {
}
}
bool Graph::IsLoaded() const {
return GetNetwork() != nullptr;
bool Graph::is_loaded() const {
return get_network() != nullptr;
}
std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPerformanceCounts() const {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::GetPerformanceCounts");
std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> result;
std::vector<ov::ProfilingInfo> Graph::get_profiling_info() const {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "Graph::get_profiling_info");
std::map<std::string, ov::ProfilingInfo> result;
bool combinePrimByIRLayers = false;
unsigned i = 0;
auto allIds = GetNetwork()->get_all_primitive_org_ids();
auto executedPrimitives = GetNetwork()->get_executed_primitives();
auto primitivesInfo = GetNetwork()->get_primitives_info();
auto extIdMap = GetNetwork()->get_ext_id_mapping();
auto allIds = get_network()->get_all_primitive_org_ids();
auto executedPrimitives = get_network()->get_executed_primitives();
auto primitivesInfo = get_network()->get_primitives_info();
auto extIdMap = get_network()->get_ext_id_mapping();
std::map<std::string, std::string> implementation_info;
if (GetNetwork()->get_program() == nullptr) {
if (get_network()->get_program() == nullptr) {
for (auto& pi : primitivesInfo) {
implementation_info[pi.original_id] = pi.kernel_id;
}
@@ -674,14 +581,12 @@ std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPer
auto& extPerfEntry = result[layerName];
memset(extPerfEntry.exec_type, 0, sizeof(extPerfEntry.exec_type));
if (perfCounter.isCPU) {
static const std::string cpuExecType("CPU");
cpuExecType.copy(extPerfEntry.exec_type, cpuExecType.length()); // Override execType as CPU
extPerfEntry.exec_type = "CPU";
} else {
std::string impl;
if (GetNetwork()->get_program() != nullptr) {
impl = GetNetwork()->get_implementation_info(primId);
if (get_network()->get_program() != nullptr) {
impl = get_network()->get_implementation_info(primId);
} else {
if (implementation_info.find(primId) != implementation_info.end()) {
impl = implementation_info[primId];
@@ -689,13 +594,13 @@ std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPer
impl = "undef";
}
}
impl.copy(extPerfEntry.exec_type, impl.length());
extPerfEntry.exec_type = impl;
}
extPerfEntry.execution_index = i++;
extPerfEntry.status = perfCounter.status;
extPerfEntry.cpu_uSec = perfCounter.cpu_avg();
extPerfEntry.realTime_uSec = perfCounter.realTime_avg();
extPerfEntry.cpu_time = std::chrono::microseconds(perfCounter.cpu_avg());
extPerfEntry.real_time = std::chrono::microseconds(perfCounter.realTime_avg());
extPerfEntry.node_name = layerName;
if (combinePrimByIRLayers) {
std::string kernelId = "";
@@ -706,8 +611,8 @@ std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPer
const auto &pc = iter->second.second;
if (id != primId && pc.parentPrimitive == primId) {
extPerfEntry.cpu_uSec += pc.cpu_avg();
extPerfEntry.realTime_uSec += pc.realTime_avg();
extPerfEntry.cpu_time += std::chrono::microseconds(pc.cpu_avg());
extPerfEntry.real_time += std::chrono::microseconds(pc.realTime_avg());
if (pc.realTime_avg() > kernelTime) {
kernelTime = pc.realTime_avg();
kernelId = id;
@@ -716,12 +621,11 @@ std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPer
}
}
if (!kernelId.empty()) {
std::string impl_info = GetNetwork()->get_implementation_info(kernelId);
std::memcpy(extPerfEntry.exec_type, &impl_info[0], impl_info.length());
extPerfEntry.exec_type = get_network()->get_implementation_info(kernelId);
}
}
getUpperCaseName(perfCounter.layerType).copy(extPerfEntry.layer_type, perfCounter.layerType.length());
extPerfEntry.node_type = getUpperCaseName(perfCounter.layerType);
return true;
};
@@ -769,25 +673,20 @@ std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPer
auto& extPerfEntry = result[layerName];
if (pi.is_cpu) {
static const std::string cpuExecType("CPU");
memset(extPerfEntry.exec_type, 0, sizeof(extPerfEntry.exec_type));
cpuExecType.copy(extPerfEntry.exec_type, cpuExecType.length()); // Override execType as CPU
extPerfEntry.exec_type = "CPU";
} else {
std::string impl = pi.kernel_id;
impl.copy(extPerfEntry.exec_type, impl.length());
extPerfEntry.exec_type = pi.kernel_id;
}
getUpperCaseName(pi.type_id).copy(extPerfEntry.layer_type, pi.type_id.length());
extPerfEntry.execution_index = i++;
extPerfEntry.status = InferenceEngineProfileInfo::LayerStatus::EXECUTED;
extPerfEntry.cpu_uSec = cpuTime;
extPerfEntry.realTime_uSec = deviceTime;
extPerfEntry.node_type = getUpperCaseName(pi.type_id);
extPerfEntry.node_name = pi.original_id;
extPerfEntry.status = ov::ProfilingInfo::Status::EXECUTED;
extPerfEntry.cpu_time = std::chrono::microseconds(cpuTime);
extPerfEntry.real_time = std::chrono::microseconds(deviceTime);
if (pi.type_id == "input_layout") {
const std::string input_string = "Input";
const std::string undef_string = "undef";
input_string.copy(extPerfEntry.layer_type, 256);
undef_string.copy(extPerfEntry.exec_type, 256);
extPerfEntry.node_type = "Input";
extPerfEntry.exec_type = "undef";
}
}
}
@@ -809,33 +708,33 @@ std::map<std::string, InferenceEngine::InferenceEngineProfileInfo> Graph::GetPer
auto second_res = result.find(getClearName(p.second));
if (first_res != result.end() && second_res != result.end() && first_res != second_res) {
std::swap(first_res->second.cpu_uSec, second_res->second.cpu_uSec);
std::swap(first_res->second.realTime_uSec, second_res->second.realTime_uSec);
std::swap(first_res->second.cpu_time, second_res->second.cpu_time);
std::swap(first_res->second.real_time, second_res->second.real_time);
std::swap(first_res->second.status, second_res->second.status);
std::swap(first_res->second.exec_type, second_res->second.exec_type);
std::swap(first_res->second.execution_index, second_res->second.execution_index);
}
}
return result;
std::vector<ov::ProfilingInfo> res;
for (auto& kv : result) {
res.push_back(kv.second);
}
return res;
}
std::shared_ptr<cldnn::network> Graph::GetNetwork(size_t idx) const {
if (idx >= GetNetworksCount())
OPENVINO_THROW("Unable to find network with id=", idx, ". Stored networks count: ", GetNetworksCount());
return m_networks[idx];
std::shared_ptr<cldnn::network> Graph::get_network() const {
return m_network;
}
std::string Graph::MapOutputName(std::string outName) const {
auto networkOutputsIDs = GetNetwork()->get_output_ids();
auto allPrimitiveIds = GetNetwork()->get_all_primitives();
std::string Graph::out_name_to_internal(std::string out_port_name) const {
auto networkOutputsIDs = get_network()->get_output_ids();
auto allPrimitiveIds = get_network()->get_all_primitives();
// Find correct output ID. Start with name stored in IR.
if (primitiveIDs.find(outName) == primitiveIDs.end()) {
OPENVINO_THROW("output with name ", outName, " was not found in primitiveIDs");
if (primitiveIDs.find(out_port_name) == primitiveIDs.end()) {
OPENVINO_THROW("output with name ", out_port_name, " was not found in primitiveIDs");
}
std::string outputID = primitiveIDs.at(outName);
std::string outputID = primitiveIDs.at(out_port_name);
while (std::find(networkOutputsIDs.begin(), networkOutputsIDs.end(), outputID) == networkOutputsIDs.end()) {
// If current ID isn't found in cldnn network outputs, get previous primitive id and try again.
auto prim = allPrimitiveIds.find(outputID);
@@ -852,17 +751,5 @@ std::string Graph::MapOutputName(std::string outName) const {
return outputID;
}
InferenceEngine::SizeVector Graph::GetOutputSize(std::string outName) const {
auto res_output = outputDims.find(outName);
InferenceEngine::SizeVector sz;
if (res_output != outputDims.end())
sz = res_output->second;
else
sz = outputDims.at(primitiveIDs.at(outName));
return sz;
}
} // namespace intel_gpu
} // namespace ov
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -5,8 +5,6 @@
#include "intel_gpu/plugin/program_builder.hpp"
#include "intel_gpu/primitives/condition.hpp"
#include "ie_ngraph_utils.hpp"
namespace ov {
namespace intel_gpu {
@@ -16,33 +14,13 @@ const size_t idx_false = 1;
static cldnn::condition::branch gen_branch(ProgramBuilder& p, const std::shared_ptr<ov::op::v8::If>& op, size_t idx) {
cldnn::condition::branch branch;
const auto& internal_body = (idx == idx_true)? op->get_then_body() : op->get_else_body();
InferenceEngine::CNNNetwork body_network(internal_body);
{
// CNNNetwork change the input/output data type to fp32 when input/output data type is fp16
// To run internal body, rollback input/output data to original one.
size_t tidx = 0;
auto& model_inputs = internal_body->get_parameters();
for (auto& in : body_network.getInputsInfo()) {
auto input_data_type = InferenceEngine::details::convertPrecision(model_inputs[tidx++]->get_output_tensor(0).get_element_type());
if (in.second->getPrecision() != input_data_type)
in.second->setPrecision(input_data_type);
}
tidx = 0;
for (auto& out : body_network.getOutputsInfo()) {
const auto& model_output = internal_body->get_output_op(tidx++);
auto output_data_type = InferenceEngine::details::convertPrecision(model_output->get_output_tensor(0).get_element_type());
if (out.second->getPrecision() != output_data_type)
out.second->setPrecision(output_data_type);
}
}
auto config = p.get_config();
config.set_property(ov::intel_gpu::max_dynamic_batch(1));
config.set_property(ov::intel_gpu::allow_new_shape_infer(op->is_dynamic()));
ProgramBuilder prog(body_network, p.get_engine(), config, false, false, nullptr, nullptr, p.get_task_executor(), true);
branch.inner_program = prog.GetCompiledProgram();
ProgramBuilder prog(internal_body, p.get_engine(), config, false, false, p.get_task_executor(), true);
branch.inner_program = prog.get_compiled_program();
auto& input_map = branch.input_map;
auto external_inputs = p.GetInputInfo(op);
@@ -23,11 +23,7 @@ static void CreateCommonConvertColorOp(ProgramBuilder& p, const std::shared_ptr<
auto inputs = p.GetInputInfo(op);
std::string layerName = layer_type_name_ID(op);
auto outDatatype = cldnn::element_type_to_data_type(op->get_input_element_type(0));
auto outShape = tensor_from_dims(op->get_output_shape(0));
outShape = { outShape.sizes()[0], outShape.sizes()[2], outShape.sizes()[3], outShape.sizes()[1] };
auto out_layout = cldnn::layout(outDatatype, cldnn::format::byxf, outShape);
auto batch = op->get_input_partial_shape(0)[0];
auto memory_type = cldnn::convert_color::memory_type::buffer;
if (op->get_input_node_ptr(0)->output(0).get_rt_info().count(ov::preprocess::TensorInfoMemoryType::get_type_info_static())) {
@@ -38,25 +34,21 @@ static void CreateCommonConvertColorOp(ProgramBuilder& p, const std::shared_ptr<
}
}
if (outShape.batch[0] > 1 && memory_type == cldnn::convert_color::memory_type::image) {
if (batch.is_static() && batch.get_length() > 1 && memory_type == cldnn::convert_color::memory_type::image) {
std::vector<cldnn::input_info> convert_color_names;
for (int b = 0; b < outShape.batch[0]; ++b) {
for (int64_t b = 0; b < batch.get_length(); ++b) {
cldnn::primitive::input_info_arr batched_inputs;
for (size_t i = 0; i < inputs.size(); ++i) {
batched_inputs.emplace_back(cldnn::input_info(inputs[i].pid + "_" + std::to_string(b), inputs[i].idx));
}
cldnn::primitive_id batched_prim_id = layerName + "_" + std::to_string(b);
convert_color_names.emplace_back(cldnn::input_info(batched_prim_id));
auto new_shape = outShape;
new_shape.batch[0] = 1;
out_layout.set_tensor(new_shape);
p.add_primitive(*op, cldnn::convert_color(batched_prim_id,
batched_inputs,
from_color,
to_color,
memory_type,
out_layout));
memory_type));
}
p.add_primitive(*op, cldnn::concatenation(layerName, convert_color_names, 0));
} else {
@@ -64,8 +56,7 @@ static void CreateCommonConvertColorOp(ProgramBuilder& p, const std::shared_ptr<
inputs,
from_color,
to_color,
memory_type,
out_layout));
memory_type));
}
}
+3 -14
View File
@@ -16,8 +16,6 @@
#include "intel_gpu/primitives/reorder.hpp"
#include "intel_gpu/graph/topology.hpp"
#include "ie_ngraph_utils.hpp"
#include <vector>
#include <algorithm>
@@ -54,9 +52,6 @@ static void CreateLoopOp(ProgramBuilder& p, const std::shared_ptr<Loop>& op) {
const auto& body_inputs = op->get_function()->get_parameters();
const auto& body_outputs = op->get_function()->get_results();
InferenceEngine::CNNNetwork body_network(op->get_function());
auto networkInputs = body_network.getInputsInfo();
auto networkOutputs = body_network.getOutputsInfo();
// Set special body ports: current_iteration input , execution condition output
auto special_body_ports = op->get_special_body_ports();
@@ -65,23 +60,17 @@ static void CreateLoopOp(ProgramBuilder& p, const std::shared_ptr<Loop>& op) {
auto current_iteration_input = body_inputs.at(special_body_ports.current_iteration_input_idx);
body_current_iteration_id = layer_type_name_ID(current_iteration_input);
std::string input_name = ov::op::util::create_ie_output_name(current_iteration_input);
const auto networkInput = networkInputs.at(input_name);
auto precision = InferenceEngine::details::convertPrecision(current_iteration_input->get_element_type());
networkInput->setPrecision(precision);
}
cldnn::primitive_id body_execution_condition_id;
if (special_body_ports.body_condition_output_idx >= 0) {
auto body_condition_output = body_outputs.at(special_body_ports.body_condition_output_idx)->get_input_node_shared_ptr(0);
body_execution_condition_id = layer_type_name_ID(body_condition_output);
std::string output_name = ov::op::util::create_ie_output_name(body_condition_output);
const auto networkOutput = networkOutputs.at(output_name);
networkOutput->setPrecision(InferenceEngine::Precision::I64);
}
// get body topology from ngraph function
ProgramBuilder body_program(body_network, p.get_engine(), p.get_config(), true);
auto body_topology = *body_program.GetTopology();
// get body topology from ov::Model
ProgramBuilder body_program(op->get_function(), p.get_engine(), p.get_config(), true);
auto body_topology = *body_program.get_topology();
// setup input_primitive_maps/ output_primitive_maps and back_edges
std::vector<cldnn::loop::io_primitive_map> input_primitive_maps;
@@ -19,122 +19,21 @@
#include "intel_gpu/primitives/data.hpp"
#include "intel_gpu/primitives/concatenation.hpp"
using namespace InferenceEngine;
namespace ov {
namespace intel_gpu {
static void CreateParameterOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v0::Parameter>& op) {
auto networkInputs = p.GetNetworkInputs();
OPENVINO_ASSERT(networkInputs.find(op->get_friendly_name()) != networkInputs.end(),
"[GPU] Can't find input ", op->get_friendly_name(), " in InputsDataMap");
auto inputInfo = networkInputs.at(op->get_friendly_name());
// first create and add the input layout
const auto inputDesc = inputInfo->getTensorDesc();
InferenceEngine::Layout l = inputDesc.getLayout();
InferenceEngine::Precision ip = inputDesc.getPrecision();
auto input_pshape = op->get_partial_shape();
if (!p.use_new_shape_infer()) {
if (input_pshape.size() < 4) {
input_pshape.insert(input_pshape.end(), 4 - input_pshape.size(), ov::Dimension(1));
}
if (p.m_max_batch > 1) {
input_pshape[0] = ov::Dimension(p.m_curBatch);
}
if (!p.use_new_shape_infer() && input_pshape.size() < 4) {
input_pshape.insert(input_pshape.end(), 4 - input_pshape.size(), ov::Dimension(1));
}
cldnn::format inputFormat = cldnn::format::get_default_format(input_pshape.size());
std::vector<size_t> default_order(input_pshape.size());
std::iota(default_order.begin(), default_order.end(), 0);
// For legacy API we need to handle NHWC as well, so check non default order
if (inputDesc.getBlockingDesc().getOrder() != default_order) {
inputFormat = FormatFromLayout(l);
}
cldnn::format input_format = cldnn::format::get_default_format(input_pshape.size());
auto element_type = cldnn::element_type_to_data_type(convert_to_supported_device_type(op->get_output_element_type(0)));
// look at the expected color format of this input
auto inputName = layer_type_name_ID(op);
auto preProcess = inputInfo->getPreProcess();
size_t meanChannels = preProcess.getNumberOfChannels();
cldnn::layout networkInputLayout(input_pshape,
cldnn::element_type_to_data_type(op->get_output_element_type(0)),
inputFormat);
cldnn::primitive_id meanBlobID = inputName + ProgramBuilder::m_meanValuesTag;
std::vector<float> meanValues;
if ((meanChannels > 0) &&
(meanChannels != static_cast<size_t>(networkInputLayout.feature()))) {
OPENVINO_THROW("Mismatched mean values channels in input ", inputName);
}
switch (preProcess.getMeanVariant()) {
case NONE:
case MEAN_VALUE: {
if (meanChannels > 0) {
for (size_t c = 0; c < meanChannels; c++) {
if (fabs(preProcess[c]->stdScale - 1.0f) > 1e-10)
OPENVINO_THROW("not supporting stdScale yet in input ", inputName);
meanValues.push_back(preProcess[c]->meanValue);
}
}
break;
}
case MEAN_IMAGE: {
OPENVINO_ASSERT(meanChannels);
// first merge all mean values to a single blob
// todo make sure mean blob precision is the same as the input precision
auto meanDims = input_pshape;
// overwrite batches with 1
switch (meanDims.size()) {
case 4: meanDims[0] = 1;
break;
default:
OPENVINO_THROW("Missing batch dimensions in input image");
}
const TensorDesc desc(Precision::FP32, meanDims.to_shape(), TensorDesc::getLayoutByDims(meanDims.to_shape()));
TBlob<float> meanBlob(desc);
meanBlob.allocate();
auto meanBlobData = meanBlob.data();
for (size_t c = 0; c < meanChannels; c++) {
if (fabs(preProcess[c]->stdScale - 1.0f) > 1e-10)
OPENVINO_THROW("not supporting stdScale yet in input ", inputName);
auto channelMeanBlob = std::dynamic_pointer_cast<TBlob<float>>(preProcess[c]->meanData);
auto channelSize = channelMeanBlob->size();
auto channelBlobData = channelMeanBlob->data();
for (size_t i = 0; i < channelSize; i++) {
meanBlobData[(c * channelSize) + i] = channelBlobData[i];
}
}
// then create a data primitive for the mean values
auto meanBlobPtr = std::make_shared<TBlob<float>>(meanBlob);
// mean values will use external format (sub in the input format before convert to new format)
cldnn::tensor meanBlobTensor(networkInputLayout.get_tensor());
meanBlobTensor.batch[0] = 1; // mean values have no batches
cldnn::layout meanBlobLayout(cldnn::data_types::f32, cldnn::format::bfyx, meanBlobTensor);
auto data = static_cast<const char *>(meanBlobPtr->buffer());
auto bufIter = p.blobMemCache.find(std::make_pair(data, meanDims.to_shape()));
if (bufIter != p.blobMemCache.end()) {
meanBlobID = bufIter->second;
} else {
auto mem = p.get_engine().allocate_memory(meanBlobLayout, false);
cldnn::mem_lock<int8_t> tmpPointer{ mem, p.get_engine().get_service_stream() };
auto buf = tmpPointer.data();
auto bufSize = meanBlobLayout.bytes_count();
std::memcpy(&buf[0], &data[0], bufSize);
p.add_primitive(*op, cldnn::data(meanBlobID, mem));
p.blobMemCache[std::make_pair(data, meanDims.to_shape())] = meanBlobID;
}
break;
}
default: OPENVINO_THROW("Invalid mean variant in input ", inputName);
break;
}
auto input_name = layer_type_name_ID(op);
cldnn::layout input_layout(input_pshape, element_type, input_format);
auto is_convert_color_type = [](const std::shared_ptr<ov::Node> &node) {
return ov::is_type<ov::op::v8::NV12toRGB>(node) ||
@@ -182,80 +81,44 @@ static void CreateParameterOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v
if (is_surface_input) {
size_t batch = input_pshape[0].get_length();
networkInputLayout.format = cldnn::format::nv12;
networkInputLayout.set_partial_shape({ 1, input_pshape[3], input_pshape[1], input_pshape[2] });
input_layout.format = cldnn::format::nv12;
input_layout.set_partial_shape({ 1, input_pshape[1], input_pshape[2], input_pshape[3] });
std::string suffix = "";
std::vector<cldnn::input_info> surfaces_inputs;
for (size_t i = 0; i < batch; ++i) {
if (batch > 1)
suffix = "_" + std::to_string(i);
std::string batched_name = inputName + suffix;
p.inputLayouts.insert({ inputInfo->name() + suffix, networkInputLayout });
p.add_primitive(*op, cldnn::input_layout(batched_name, networkInputLayout));
std::string batched_name = input_name + suffix;
p.inputLayouts.insert({ op->get_friendly_name() + suffix, input_layout });
p.add_primitive(*op, cldnn::input_layout(batched_name, input_layout));
auto reorder_layout = networkInputLayout;
auto reorder_layout = input_layout;
reorder_layout.format = cldnn::format::bfyx;
auto preprocessPrimID = "reorder:" + inputName + ProgramBuilder::m_preProcessTag + suffix;
auto reorder = cldnn::reorder(preprocessPrimID,
auto reorder_name = "reorder:" + input_name + ProgramBuilder::m_preProcessTag + suffix;
auto reorder = cldnn::reorder(reorder_name,
cldnn::input_info(batched_name),
reorder_layout);
reorder.input_mem_type = cldnn::reorder::memory_type::surface;
p.add_primitive(*op, reorder);
surfaces_inputs.push_back(cldnn::input_info(preprocessPrimID));
surfaces_inputs.emplace_back(reorder_name);
}
if (batch > 1 && !is_convert_color_input)
p.add_primitive(*op, cldnn::concatenation(inputName, surfaces_inputs, 0));
p.add_primitive(*op, cldnn::concatenation(input_name, surfaces_inputs, 0));
else
p.primitive_ids[inputName] = "reorder:" + inputName + ProgramBuilder::m_preProcessTag;
} else if (is_convert_color_input) {
networkInputLayout.format = cldnn::format::byxf;
networkInputLayout.set_partial_shape({ input_pshape[0], input_pshape[3], input_pshape[1], input_pshape[2] });
p.inputLayouts.insert({ inputInfo->name(), networkInputLayout });
p.add_primitive(*op, cldnn::input_layout(inputName, networkInputLayout));
p.primitive_ids[input_name] = "reorder:" + input_name + ProgramBuilder::m_preProcessTag;
} else {
auto preprocessPrimID = "reorder:" + inputName + ProgramBuilder::m_preProcessTag;
cldnn::layout inputLayout(networkInputLayout);
auto network_input_data_type = DataTypeFromPrecision(ip);
inputLayout.data_type = network_input_data_type;
p.inputLayouts.insert({ inputInfo->name(), inputLayout });
auto reorder_name = "reorder:" + input_name + ProgramBuilder::m_preProcessTag;
p.inputLayouts.insert({ op->get_friendly_name(), input_layout });
p.add_primitive(*op, cldnn::input_layout(inputName, inputLayout));
p.add_primitive(*op, cldnn::input_layout(input_name, input_layout));
switch (preProcess.getMeanVariant()) {
case NONE: {
// If mean value is not specified and the data type does not change, do not add post reorder
if (network_input_data_type != networkInputLayout.data_type || connected_to_quantize(op)) {
p.add_primitive(*op, cldnn::reorder(preprocessPrimID,
cldnn::input_info(inputName),
networkInputLayout,
meanValues,
cldnn::reorder_mean_mode::none), {inputName});
}
break;
}
case MEAN_VALUE: {
p.add_primitive(*op, cldnn::reorder(preprocessPrimID,
cldnn::input_info(inputName),
networkInputLayout,
meanValues,
cldnn::reorder_mean_mode::subtract), {inputName});
break;
}
case MEAN_IMAGE: {
p.add_primitive(*op, cldnn::reorder(preprocessPrimID,
cldnn::input_info(inputName),
networkInputLayout,
meanBlobID,
cldnn::reorder_mean_mode::subtract), {inputName});
break;
}
default: OPENVINO_THROW("Invalid mean variant in input ", inputName);
break;
if (connected_to_quantize(op)) {
// Techically this reorder is not needed, but for some reason it impacts layout propagation logic
// TODO: Remove it and fix layout assignment & propagation passes
p.add_primitive(*op, cldnn::reorder(reorder_name, cldnn::input_info(input_name), input_layout), {input_name});
}
}
}
+14 -66
View File
@@ -12,88 +12,36 @@
#include "intel_gpu/plugin/common_utils.hpp"
#include "intel_gpu/primitives/reorder.hpp"
using namespace InferenceEngine;
namespace ov {
namespace intel_gpu {
static void CreateResultOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v0::Result>& op) {
OutputsDataMap networkOutputs = p.GetNetworkOutputs();
validate_inputs_count(op, {1});
auto prev = op->get_input_node_shared_ptr(0);
NGRAPH_SUPPRESS_DEPRECATED_START
auto inputID = ov::descriptor::get_ov_tensor_legacy_name(op->get_input_source_output(0).get_tensor());
NGRAPH_SUPPRESS_DEPRECATED_END
if (inputID.empty()) {
inputID = prev->get_friendly_name();
OPENVINO_SUPPRESS_DEPRECATED_START
auto input_id = ov::descriptor::get_ov_tensor_legacy_name(op->get_input_source_output(0).get_tensor());
OPENVINO_SUPPRESS_DEPRECATED_END
if (input_id.empty()) {
input_id = prev->get_friendly_name();
if (prev->get_output_size() > 1) {
inputID += "." + std::to_string(op->get_input_source_output(0).get_index());
input_id += "." + std::to_string(op->get_input_source_output(0).get_index());
}
}
auto it = networkOutputs.find(inputID);
OPENVINO_ASSERT(it != networkOutputs.end(), "[GPU] Can't find output ", inputID, " in OutputsDataMap");
std::string originalOutName = it->first;
DataPtr outputData = it->second;
auto inputs = p.GetInputInfo(op);
const auto outputDesc = outputData->getTensorDesc();
auto outputlayout = outputDesc.getLayout();
if (ov::is_type<ov::op::v8::NV12toRGB>(prev) ||
ov::is_type<ov::op::v8::NV12toBGR>(prev) ||
ov::is_type<ov::op::v8::I420toRGB>(prev) ||
ov::is_type<ov::op::v8::I420toBGR>(prev)) {
outputlayout = NHWC;
}
// TODO: add precision check once there's an outputInfo object
if (outputlayout != NCHW &&
// TODO: change 6d case once new layout added in IE
outputlayout != BLOCKED &&
outputlayout != NCDHW &&
outputlayout != NHWC &&
outputlayout != CHW &&
outputlayout != NC &&
outputlayout != C &&
outputlayout != SCALAR) {
OPENVINO_THROW("[GPU] Unsupported layout (", outputlayout, ") in output: ", originalOutName);
}
auto out_rank = op->get_output_partial_shape(0).size();
auto out_format = cldnn::format::get_default_format(out_rank);
std::vector<size_t> default_order(out_rank);
std::iota(default_order.begin(), default_order.end(), 0);
// For legacy API we need to handle NHWC as well, so check non default order
if (outputlayout == NHWC) {
out_format = FormatFromLayout(outputlayout);
}
auto outLayerName = layer_type_name_ID(op);
auto inputDataType = cldnn::element_type_to_data_type(op->get_input_element_type(0));
Precision precision = outputData->getPrecision();
auto outputDataType = DataTypeFromPrecision(precision);
cldnn::input_info outputID = inputs[0];
auto out_primitive_name = layer_type_name_ID(op);
auto out_data_type = cldnn::element_type_to_data_type(convert_to_supported_device_type(op->get_input_element_type(0)));
// Even for result op, if reorder only performs type conversion, reorder is created in truncation mode
if (inputDataType != outputDataType) {
auto reorder_primitive = cldnn::reorder(outLayerName,
outputID,
out_format,
outputDataType,
std::vector<float>(),
cldnn::reorder_mean_mode::subtract,
cldnn::padding(),
true);
p.add_primitive(*op, reorder_primitive, {originalOutName});
} else {
auto reorder_primitive = cldnn::reorder(outLayerName,
outputID,
out_format,
outputDataType);
p.add_primitive(*op, reorder_primitive, {originalOutName});
}
p.outputDims[originalOutName] = outputDesc.getDims();
p.prevPrimitiveIDs[outLayerName] = {originalOutName};
auto reorder_primitive = cldnn::reorder(out_primitive_name,
inputs[0],
out_format,
out_data_type);
p.add_primitive(*op, reorder_primitive, {input_id, op->get_friendly_name()});
p.prevPrimitiveIDs[out_primitive_name] = {input_id};
}
REGISTER_FACTORY_IMPL(v0, Result);
@@ -49,10 +49,8 @@ static cldnn::mutable_data CreateAdditionalOutputData(ProgramBuilder &p, const s
static void CreateTensorIteratorOp(ProgramBuilder &p, const std::shared_ptr<TensorIterator> &op) {
auto inputs = p.GetInputInfo(op);
// get body topology from ngraph function
InferenceEngine::CNNNetwork body_network(op->get_body());
ProgramBuilder body_program(body_network, p.get_engine(), p.get_config(), true);
auto body_topology = *body_program.GetTopology();
ProgramBuilder body_program(op->get_body(), p.get_engine(), p.get_config(), true);
auto body_topology = *body_program.get_topology();
// setup input_primitive_maps/ output_primitive_maps and back_edges
const auto& loop_input_descs = op->get_input_descriptions();
@@ -4,16 +4,10 @@
#include "openvino/op/transpose.hpp"
#include "openvino/op/constant.hpp"
#include "openvino/op/convert.hpp"
#include "openvino/op/nv12_to_rgb.hpp"
#include "openvino/op/nv12_to_bgr.hpp"
#include "openvino/op/i420_to_rgb.hpp"
#include "openvino/op/i420_to_bgr.hpp"
#include "intel_gpu/plugin/program_builder.hpp"
#include "intel_gpu/plugin/common_utils.hpp"
#include "intel_gpu/primitives/permute.hpp"
#include "intel_gpu/primitives/reorder.hpp"
namespace ov {
namespace intel_gpu {
@@ -30,39 +24,6 @@ static void CreateTransposeOp(ProgramBuilder& p, const std::shared_ptr<ov::op::v
order = order_constant->cast_vector<uint16_t>();
}
auto is_convert_color_type_impl = [](const std::shared_ptr<ov::Node> &node) {
return ov::is_type<ov::op::v8::NV12toRGB>(node) ||
ov::is_type<ov::op::v8::NV12toBGR>(node) ||
ov::is_type<ov::op::v8::I420toRGB>(node) ||
ov::is_type<ov::op::v8::I420toBGR>(node);
};
auto is_convert_color_type = [&is_convert_color_type_impl](const std::shared_ptr<ov::Node> &node) {
if (ngraph::is_type<ov::op::v0::Convert>(node)) {
return is_convert_color_type_impl(node->get_input_node_shared_ptr(0));
}
return is_convert_color_type_impl(node);
};
// Handle Transpose operation related to ConvertColor operation:
// In case of ConvertColor operation we have NHWC (byxf) input format which should be converted to
// NCHW (bfyx) by this Permute, so we replace Permute with Reorder (to bfyx) primitve
auto input = op->get_input_size() > 0 ? op->get_input_node_shared_ptr(0) : nullptr;
// Handle the case ConvertColor -> FakeQuantize -> Permute
auto input1 = input ? (input->get_input_size() > 0 ? input->get_input_node_shared_ptr(0) : nullptr) : nullptr;
if (((input && is_convert_color_type(input)) || (input1 && is_convert_color_type(input1)))
&& order == std::vector<uint16_t>{0, 3, 1, 2}) {
auto precision = input->get_element_type();
auto reorder_prim = cldnn::reorder(layerName,
inputs[0],
cldnn::format::bfyx,
cldnn::element_type_to_data_type(precision),
std::vector<float>(),
cldnn::reorder_mean_mode::none);
p.add_primitive(*op, reorder_prim);
return;
}
int rank = std::max(4, static_cast<int>(op->get_input_partial_shape(0).size()));
if (order.empty()) {
// if order size is less than 4 - fill the rest with just copy
File diff suppressed because it is too large. Load diff
@@ -25,14 +25,10 @@
#endif
using namespace InferenceEngine;
using namespace InferenceEngine::details;
namespace ov {
namespace intel_gpu {
const cldnn::primitive_id ProgramBuilder::m_preProcessTag("_cldnn_input_preprocess");
const cldnn::primitive_id ProgramBuilder::m_meanValuesTag("_cldnn_mean_values");
const cldnn::primitive_id ProgramBuilder::m_preCustomLayerTag("_cldnn_custom_preprocess");
const cldnn::primitive_id ProgramBuilder::m_postCustomLayerTag("_cldnn_custom_postprocess");
ProgramBuilder::factories_map_t ProgramBuilder::factories_map = {};
@@ -57,93 +53,15 @@ std::string layer_type_name_ID(const std::shared_ptr<ov::Node>& op) {
return layer_type_name_ID(op.get());
}
void ProgramBuilder::ChangeInputBatch(int batch) {
m_curBatch = batch;
}
auto getParamName = [](const std::shared_ptr<ov::Node>& param) -> std::string {
const auto& names = param->get_output_tensor(0).get_names();
if (!names.empty())
return *names.begin();
else
return param->get_friendly_name();
};
// detect the only supported dynamic shape case -
// exactly one dimension is dynamic in input params with defined min/max interval
bool ProgramBuilder::IsDynBatchModel(const std::shared_ptr<ov::Model>& model,
std::map<std::string, ov::PartialShape>& shapes,
std::map<std::string, std::pair<int64_t, int64_t>>& batch_dim) {
for (const auto& param : model->get_parameters()) {
auto pname = getParamName(param);
batch_dim[pname] = { -1, -1 };
if (param->get_output_partial_shape(0).rank().is_dynamic()) {
return false;
}
ov::PartialShape pshape = param->get_output_partial_shape(0);
bool only_batch_dynamic = pshape.size() && pshape[0].is_dynamic();
for (size_t i = 1; i < pshape.size(); i++) {
if (pshape[i].is_dynamic()) {
// only support 0th dimension for legacy dynamic batch
return false;
}
}
if (only_batch_dynamic) {
int64_t max_b = pshape[0].get_max_length();
if (max_b > 1) {
batch_dim[pname].first = 0;
batch_dim[pname].second = max_b;
pshape[0] = 1;
} else {
// unbounded dynamic shape should be handled with new dynamic shape path
return false;
}
}
shapes[pname] = pshape;
}
if (batch_dim.empty())
return false;
bool dyn_shape_batch_found = false;
// detect 1st dyn dim, mark it and continue
auto bitr = batch_dim.begin();
dyn_shape_batch_found = (bitr->second.first == 0);
auto batch_val_1st = bitr->second.second;
bitr++;
for (; bitr != batch_dim.end(); bitr++) {
if (bitr->second.first == 0) {
if (bitr->second.second != batch_val_1st) {
dyn_shape_batch_found = false;
break;
} else {
dyn_shape_batch_found = true;
}
} else {
return false;
}
}
return dyn_shape_batch_found;
}
ProgramBuilder::ProgramBuilder(InferenceEngine::CNNNetwork& network, cldnn::engine& engine, const ExecutionConfig& config,
bool createTopologyOnly, bool partialBuild,
InferenceEngine::InputsDataMap* inputs, InferenceEngine::OutputsDataMap* outputs,
std::shared_ptr<ov::threading::IStreamsExecutor> task_executor, bool innerProgram)
: m_curBatch(-1)
, m_config(config)
ProgramBuilder::ProgramBuilder(std::shared_ptr<ov::Model> model, cldnn::engine& engine, const ExecutionConfig& config,
bool create_topology_only, bool partial_build,
std::shared_ptr<ov::threading::IStreamsExecutor> task_executor, bool is_inner_program)
: m_config(config)
, m_engine(engine)
, queryMode(false)
, m_task_executor(task_executor) {
if (m_task_executor == nullptr)
m_task_executor = cldnn::program::make_task_executor(m_config);
// Extract inputs/outputs info from CNNNetwork
auto networkInputs = (inputs != nullptr) ? *inputs : network.getInputsInfo();
auto networkOutputs = (outputs != nullptr) ? *outputs : network.getOutputsInfo();
auto func = network.getFunction();
if (!func) {
OPENVINO_THROW("Function pointer inside CNNNetwork is nullptr");
}
// locate global custom kernel config
// and auto-load kernels from it
@@ -175,186 +93,28 @@ ProgramBuilder::ProgramBuilder(InferenceEngine::CNNNetwork& network, cldnn::engi
auto custom_layers_config = m_config.get_property(ov::intel_gpu::config_file);
CustomLayer::LoadFromFile(custom_layers_config, m_custom_layers, custom_layers_config.empty());
auto ops = func->get_ordered_ops();
auto ops = model->get_ordered_ops();
bool dyn_shape_batch_found = false;
std::map<std::string, ov::PartialShape> shapes;
std::map<std::string, std::pair<int64_t, int64_t>> batch_dim;
dyn_shape_batch_found = IsDynBatchModel(func, shapes, batch_dim);
if (dyn_shape_batch_found) {
m_config.set_property(ov::intel_gpu::max_dynamic_batch(batch_dim.begin()->second.second));
}
int m_bv_sz = GetMaxBatchSizeForSingleProgram();
m_max_batch = static_cast<int>(m_config.get_property(ov::intel_gpu::max_dynamic_batch));
// Do not apply dynamic batch for inner program (only single batch is allowed)
if (!innerProgram && (dyn_shape_batch_found || m_max_batch > 1)) {
// compile log2 networks to serve dynamic batch requests
for (int b = m_bv_sz - 1; b >= 0; b--) {
inputLayouts.clear();
outputDims.clear();
primitive_ids.clear();
blobMemCache.clear();
auto new_batch = 1U << static_cast<unsigned>(b);
ChangeInputBatch(new_batch);
// clone the source model, find the batch dim
// and reshape the model to next batch size
auto new_func = func->clone();
std::map<ov::Output<ov::Node>, ov::PartialShape> new_shapes;
for (const auto& param : new_func->get_parameters()) {
ov::PartialShape pshape = param->get_output_partial_shape(0);
auto pname = getParamName(param);
auto batch_idx = batch_dim[pname].first;
if (batch_idx >= 0) {
auto pshape = shapes[pname];
pshape[batch_idx] = new_batch;
new_shapes[param->output(0)] = pshape;
}
}
new_func->reshape(new_shapes);
{
auto deviceInfo = engine.get_device_info();
TransformationsPipeline transformations(m_config, deviceInfo);
transformations.apply(new_func);
}
// reshape network input/output maps accordingly
// for correct network compilation
for (auto& new_input : new_func->inputs()) {
auto iname = new_input.get_node()->get_friendly_name();
auto it = networkInputs.find(iname);
if (it != networkInputs.end()) {
auto shape = new_input.get_shape();
auto l = it->second->getTensorDesc().getLayout();
it->second->getInputData()->reshape(shape, l);
}
}
for (auto& new_output : new_func->outputs()) {
auto iname = new_output.get_node_shared_ptr()->get_input_source_output(0).get_node_shared_ptr()->get_friendly_name();
auto it = networkOutputs.find(iname);
if (it != networkOutputs.end()) {
auto shape = new_output.get_shape();
auto l = it->second->getTensorDesc().getLayout();
it->second->reshape(shape, l);
}
}
m_programs.insert(m_programs.begin(), BuildProgram(new_func->get_ordered_ops(), networkInputs, networkOutputs,
createTopologyOnly, partialBuild));
}
{
// recompute maximal dynamic batch inputs/outputs for infer request
// and store them into internal maps
// same operations as above, but for maximum batch
auto new_func = func->clone();
std::map<ov::Output<ov::Node>, ov::PartialShape> new_shapes;
for (const auto& param : new_func->get_parameters()) {
ov::PartialShape pshape = param->get_output_partial_shape(0);
auto pname = getParamName(param);
auto batch_idx = batch_dim[pname].first;
if (batch_idx >= 0) {
auto pshape = shapes[pname];
pshape[batch_idx] = m_max_batch;
new_shapes[param->output(0)] = pshape;
}
}
new_func->reshape(new_shapes);
for (auto& new_input : new_func->inputs()) {
auto iname = new_input.get_node()->get_friendly_name();
auto it = networkInputs.find(iname);
if (it != networkInputs.end()) {
auto shape = new_input.get_shape();
auto l = it->second->getTensorDesc().getLayout();
it->second->getInputData()->reshape(shape, l);
}
}
for (auto& new_output : new_func->outputs()) {
auto iname = new_output.get_node_shared_ptr()->get_input_source_output(0).get_node_shared_ptr()->get_friendly_name();
auto it = networkOutputs.find(iname);
if (it != networkOutputs.end()) {
auto shape = new_output.get_shape();
auto l = it->second->getTensorDesc().getLayout();
SizeVector old_shape = it->second->getTensorDesc().getDims();
it->second->reshape(shape, l);
// detect changed output batch dimension
SizeVector new_shape = it->second->getTensorDesc().getDims();
for (int64_t i = 0; i < static_cast<int64_t>(old_shape.size()); i++) {
if (old_shape[i] != new_shape[i]) {
m_output_batch_dim[iname] = i;
break;
}
}
}
}
m_networkInputs = networkInputs;
m_networkOutputs = networkOutputs;
m_input_batch_dim = batch_dim;
}
} else {
m_programs.emplace_back(BuildProgram(ops, networkInputs, networkOutputs, createTopologyOnly, partialBuild, innerProgram));
}
m_program = build(ops, create_topology_only, partial_build, is_inner_program);
}
ProgramBuilder::ProgramBuilder(cldnn::engine& engine, const ExecutionConfig& config,
InferenceEngine::InputsDataMap* inputs, InferenceEngine::OutputsDataMap* outputs)
: m_max_batch(1)
, m_curBatch(-1)
, m_config(config)
ProgramBuilder::ProgramBuilder(cldnn::engine& engine, const ExecutionConfig& config)
: m_config(config)
, m_engine(engine)
, queryMode(false) {
m_task_executor = cldnn::program::make_task_executor(m_config);
if (inputs != nullptr)
m_networkInputs = *inputs;
if (outputs != nullptr)
m_networkOutputs = *outputs;
}
int ProgramBuilder::GetMaxBatchSizeForSingleProgram() {
auto max_dynamic_batch = m_config.get_property(ov::intel_gpu::max_dynamic_batch);
if (max_dynamic_batch > 1) {
// calculate number of networks necessary based on binary log
unsigned int tmp = static_cast<unsigned int>(max_dynamic_batch);
unsigned int mask = 1U << 31;
unsigned int ldigit = 31;
while (!(tmp & mask)) {
mask >>= 1;
ldigit--;
}
return ldigit + 1;
}
return 0;
std::shared_ptr<cldnn::program> ProgramBuilder::get_compiled_program() const {
return m_program;
}
std::shared_ptr<cldnn::program> ProgramBuilder::GetCompiledProgram(int program_id) {
if (program_id >= static_cast<int32_t>(m_programs.size()))
OPENVINO_THROW("Invalid program ID");
return m_programs[program_id];
}
void ProgramBuilder::PrepareBuild(InferenceEngine::InputsDataMap networkInputs, InferenceEngine::OutputsDataMap networkOutputs) {
void ProgramBuilder::prepare_build() {
m_topology.reset(new cldnn::topology());
m_networkInputs = networkInputs;
m_networkOutputs = networkOutputs;
}
void ProgramBuilder::CleanupBuild() {
void ProgramBuilder::cleanup_build() {
m_topology.reset();
m_networkInputs.clear();
m_networkOutputs.clear();
#if defined(__unix__) && !defined(__ANDROID__)
// NOTE: In linux, without malloc_trim, an amount of the memory used by compilation is not being returned to system thought they are freed.
// (It is at least 500 MB when we perform parallel compilation)
@@ -365,12 +125,9 @@ void ProgramBuilder::CleanupBuild() {
#endif
}
std::shared_ptr<cldnn::program> ProgramBuilder::BuildProgram(const std::vector<std::shared_ptr<ov::Node>>& ops,
InferenceEngine::InputsDataMap networkInputs,
InferenceEngine::OutputsDataMap networkOutputs,
bool createTopologyOnly, bool partialBuild, bool innerProgram) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "ProgramBuilder::BuildProgram");
// std::cout << "BuildProgram " << createTopologyOnly << ", " << partialBuild << ", " << innerProgram << std::endl;
std::shared_ptr<cldnn::program> ProgramBuilder::build(const std::vector<std::shared_ptr<ov::Node>>& ops,
bool create_topology_only, bool partial_build, bool is_inner_program) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "ProgramBuilder::build");
// In the case of inner program, allow_new_shape_infer flag is setted by outside of program.
// So, do not check allow_new_shape_infer for inner program build
for (const auto& op : ops) {
@@ -380,22 +137,22 @@ std::shared_ptr<cldnn::program> ProgramBuilder::BuildProgram(const std::vector<s
}
}
if (innerProgram) {
if (is_inner_program) {
allow_new_shape_infer = (m_config.get_property(ov::intel_gpu::allow_new_shape_infer) || allow_new_shape_infer);
}
m_config.set_property(ov::intel_gpu::partial_build_program(partialBuild));
m_config.set_property(ov::intel_gpu::partial_build_program(partial_build));
m_config.set_property(ov::intel_gpu::optimize_data(true));
m_config.set_property(ov::intel_gpu::allow_new_shape_infer(allow_new_shape_infer));
PrepareBuild(networkInputs, networkOutputs);
prepare_build();
{
GPU_DEBUG_DEFINE_MEM_LOGGER("CreateSingleLayerPrimitives");
for (const auto& op : ops) {
CreateSingleLayerPrimitive(*m_topology, op);
}
}
if (createTopologyOnly) {
if (create_topology_only) {
return {};
} else {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "ProgramBuilder::CreateProgram");
@@ -403,20 +160,20 @@ std::shared_ptr<cldnn::program> ProgramBuilder::BuildProgram(const std::vector<s
try {
program = cldnn::program::build_program(m_engine, *m_topology, m_config, get_task_executor());
} catch (std::exception& e) {
OPENVINO_ASSERT(false, "GPU program build failed!\n", e.what());
OPENVINO_ASSERT(false, "[GPU] ProgramBuilder build failed!\n", e.what());
}
CleanupBuild();
cleanup_build();
return program;
}
}
bool ProgramBuilder::IsOpSupported(const InferenceEngine::CNNNetwork& network, const std::shared_ptr<ov::Node>& op) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "ProgramBuilder::IsOpSupported");
bool ProgramBuilder::is_op_supported(const std::shared_ptr<ov::Node>& op) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "ProgramBuilder::is_op_supported");
cldnn::topology topology;
try {
// Query mode disables checks that input primitives are created,
// as IsOpSupported method is called for each operation separately
// as is_op_supported method is called for each operation separately
// So we just ensure that inputs count is valid for given operation
EnableQueryMode();
// Creating topology object for each operation is supposed to be more time-consuming than
@@ -425,14 +182,14 @@ bool ProgramBuilder::IsOpSupported(const InferenceEngine::CNNNetwork& network, c
// add any ugly macro/templates to apply single function to multiple cases.
// 2. We also check parameters of each operation, which means we have more
// reliable results of QueryNetwork call.
PrepareBuild(network.getInputsInfo(), network.getOutputsInfo());
prepare_build();
allow_new_shape_infer = requires_new_shape_infer(*op);
CreateSingleLayerPrimitive(topology, op);
CleanupBuild();
cleanup_build();
DisableQueryMode();
} catch (std::exception&) {
// Exception means that an operation or some of it's parameters are not supported
CleanupBuild();
cleanup_build();
return false;
}
@@ -505,7 +262,7 @@ void ProgramBuilder::init_profile_info(const cldnn::primitive& prim) {
perfMap[prim.id].first = prim.id;
auto& perfEntry = perfMap[prim.id].second;
perfEntry.layerType = prim.origin_op_type_name;
perfEntry.status = InferenceEngine::InferenceEngineProfileInfo::LayerStatus::EXECUTED;
perfEntry.status = ov::ProfilingInfo::Status::EXECUTED;
perfEntry.cpu_uSec = perfEntry.realTime_uSec = 0;
perfEntry.isCPU = false;
perfEntry.parentPrimitive = prim.origin_op_name;
@@ -2,67 +2,36 @@
// SPDX-License-Identifier: Apache-2.0
//
#include <memory>
#include "intel_gpu/plugin/remote_allocators.hpp"
#include "intel_gpu/plugin/remote_blob.hpp"
using namespace InferenceEngine;
using namespace InferenceEngine::gpu;
using namespace InferenceEngine::details;
#include "intel_gpu/plugin/remote_tensor.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include <memory>
namespace ov {
namespace intel_gpu {
void RemoteAllocator::regLockedBlob(void* handle, const RemoteBlobImpl* blob) {
std::lock_guard<RemoteAllocator> locker(*this);
auto iter = m_lockedBlobs.find(handle);
if (iter == m_lockedBlobs.end()) {
m_lockedBlobs.emplace(handle, blob);
}
}
void RemoteAllocator::unlock(void* handle) noexcept {
std::lock_guard<RemoteAllocator> locker(*this);
auto iter = m_lockedBlobs.find(handle);
if (iter != m_lockedBlobs.end()) {
iter->second->unlock();
m_lockedBlobs.erase(iter);
}
}
void* USMHostAllocator::lock(void* handle, InferenceEngine::LockOp) noexcept {
if (!_usm_host_blob)
return nullptr;
void* USMHostAllocator::allocate(const size_t bytes, const size_t /* alignment */) noexcept {
try {
return _usm_host_blob->get();
} catch (...) {
return nullptr;
}
};
void USMHostAllocator::unlock(void* handle) noexcept {}
void* USMHostAllocator::alloc(size_t size) noexcept {
try {
auto td = TensorDesc(Precision::U8, SizeVector{size}, InferenceEngine::Layout::C);
ParamMap params = {{GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(USM_HOST_BUFFER)}};
_usm_host_blob = std::dynamic_pointer_cast<USMBlob>(_context->CreateBlob(td, params));
_usm_host_blob->allocate();
if (!getBlobImpl(_usm_host_blob.get())->is_allocated()) {
return nullptr;
ov::AnyMap params = { ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::USM_HOST_BUFFER) };
_usm_host_tensor = _context->create_tensor(ov::element::u8, {bytes}, params);
if (auto casted = std::dynamic_pointer_cast<RemoteTensorImpl>(_usm_host_tensor._ptr)) {
return casted->get_original_memory()->get_internal_params().mem;
}
return _usm_host_blob->get();
} catch (...) {
return nullptr;
} catch (std::exception&) {
return nullptr;
}
}
bool USMHostAllocator::free(void* handle) noexcept {
bool USMHostAllocator::deallocate(void* /* handle */, const size_t /* bytes */, size_t /* alignment */) noexcept {
try {
_usm_host_blob = nullptr;
} catch(...) { }
_usm_host_tensor = {nullptr, nullptr};
} catch (std::exception&) { }
return true;
}
bool USMHostAllocator::is_equal(const USMHostAllocator& other) const {
return other._usm_host_tensor != nullptr && _usm_host_tensor != nullptr && other._usm_host_tensor._ptr == _usm_host_tensor._ptr;
}
} // namespace intel_gpu
} // namespace ov
@@ -1,300 +0,0 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <memory>
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/remote_blob.hpp"
#include "intel_gpu/plugin/remote_allocators.hpp"
#include "intel_gpu/plugin/plugin.hpp"
#include "intel_gpu/runtime/itt.hpp"
using namespace InferenceEngine;
using namespace InferenceEngine::gpu;
using namespace InferenceEngine::details;
namespace ov {
namespace intel_gpu {
RemoteBlobImpl::RemoteBlobImpl(InferenceEngine::gpu::ClContext::Ptr context,
cldnn::stream& stream,
const cldnn::layout& layout,
cldnn::shared_handle mem,
cldnn::shared_surface surf,
uint32_t plane,
BlobType mem_type)
: m_allocator(std::make_shared<RemoteAllocator>())
, m_context(context)
, m_stream(stream)
, m_mem(mem)
, m_surf(surf)
, m_plane(plane)
, m_layout(layout)
, m_mem_type(mem_type)
, m_hash(0)
, m_memory_object(nullptr)
, lockedCounter(0)
, lockedHolder(nullptr)
, _handle(nullptr) {
if (supports_caching()) {
m_hash = cldnn::hash_combine(0, m_mem);
m_hash = cldnn::hash_combine(m_hash, m_surf);
m_hash = cldnn::hash_combine(m_hash, plane);
m_hash = cldnn::hash_combine(m_hash, static_cast<std::underlying_type<cldnn::format::type>::type>(layout.format));
m_hash = cldnn::hash_combine(m_hash, static_cast<std::underlying_type<cldnn::data_types>::type>(layout.data_type));
for (auto& d : layout.get_shape()) {
m_hash = cldnn::hash_combine(m_hash, d);
}
}
}
AnyMap RemoteBlobImpl::getParams() const {
OPENVINO_ASSERT(is_allocated(), "[GPU] Can't get RemoteBlob params as blob wasn't allocated properly");
auto params = m_memory_object->get_internal_params();
switch (m_mem_type) {
case BlobType::BT_BUF_INTERNAL:
case BlobType::BT_BUF_SHARED:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(OCL_BUFFER) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem }
};
case BlobType::BT_USM_SHARED:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(USM_USER_BUFFER) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem }
};
case BlobType::BT_USM_HOST_INTERNAL:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(USM_HOST_BUFFER) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem }
};
case BlobType::BT_USM_DEVICE_INTERNAL:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(USM_DEVICE_BUFFER) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem }
};
#ifdef _WIN32
case BlobType::BT_DX_BUF_SHARED:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(DX_BUFFER) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(VA_DEVICE), params.user_device },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem },
{ GPU_PARAM_KEY(DEV_OBJECT_HANDLE), params.surface }
};
#endif
case BlobType::BT_IMG_SHARED:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(OCL_IMAGE2D) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem }
};
case BlobType::BT_SURF_SHARED:
return{
{ GPU_PARAM_KEY(SHARED_MEM_TYPE), GPU_PARAM_VALUE(VA_SURFACE) },
{ GPU_PARAM_KEY(OCL_CONTEXT), params.context },
{ GPU_PARAM_KEY(VA_DEVICE), params.user_device },
{ GPU_PARAM_KEY(MEM_HANDLE), params.mem },
{ GPU_PARAM_KEY(DEV_OBJECT_HANDLE), params.surface },
{ GPU_PARAM_KEY(VA_PLANE), params.plane }
};
default:
OPENVINO_THROW("Unsupported shared object type ", static_cast<int>(m_mem_type));
}
}
void RemoteBlobImpl::setShape(const SizeVector& dims) {
if (ov::shape_size(dims) > m_memory_object->count()) {
OPENVINO_ASSERT(!is_shared(), "Cannot call setShape for Blobs created on top of preallocated memory if shape was increased.");
if (!deallocate()) {
OPENVINO_THROW("Cannot deallocate blob while an attempt to enlarge blob area in setShape.");
}
m_layout.set_partial_shape(ov::PartialShape{dims});
allocate();
}
}
bool RemoteBlobImpl::deallocate() noexcept {
m_memory_object.reset();
return m_memory_object == nullptr;
}
bool RemoteBlobImpl::is_allocated() const noexcept {
return m_memory_object != nullptr;
}
bool RemoteBlobImpl::is_locked() const noexcept {
return lockedHolder != nullptr;
}
void RemoteBlobImpl::allocate() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "RemoteBlobImpl::Allocate");
auto context = get_context_impl(m_context);
auto enable_caching = supports_caching();
if (enable_caching) {
m_memory_object = context->try_get_cached_memory(m_hash);
if (m_memory_object)
return;
}
auto& engine = context->get_engine();
switch (m_mem_type) {
case BlobType::BT_BUF_INTERNAL: {
m_memory_object = engine.allocate_memory(m_layout, cldnn::allocation_type::cl_mem);
break;
}
case BlobType::BT_USM_HOST_INTERNAL: {
m_memory_object = engine.allocate_memory(m_layout, cldnn::allocation_type::usm_host);
break;
}
case BlobType::BT_USM_DEVICE_INTERNAL: {
m_memory_object = engine.allocate_memory(m_layout, cldnn::allocation_type::usm_device);
break;
}
case BlobType::BT_BUF_SHARED: {
m_memory_object = engine.share_buffer(m_layout, m_mem);
break;
}
case BlobType::BT_USM_SHARED: {
m_memory_object = engine.share_usm(m_layout, m_mem);
break;
}
#ifdef _WIN32
case BlobType::BT_SURF_SHARED: {
m_memory_object = engine.share_surface(m_layout, m_mem, m_plane);
break;
}
case BlobType::BT_DX_BUF_SHARED: {
m_memory_object = engine.share_dx_buffer(m_layout, m_mem);
break;
}
#else
case BlobType::BT_SURF_SHARED: {
m_memory_object = engine.share_surface(m_layout, m_surf, m_plane);
break;
}
#endif
case BlobType::BT_IMG_SHARED: {
m_memory_object = engine.share_image(m_layout, m_mem);
break;
}
default:
m_memory_object.reset();
}
if (enable_caching)
context->add_to_cache(m_hash, m_memory_object);
}
const std::shared_ptr<IAllocator>& RemoteBlobImpl::getAllocator() const noexcept {
return m_allocator;
};
std::string RemoteBlobImpl::getDeviceName() const noexcept {
return m_context->getDeviceName();
};
std::shared_ptr<InferenceEngine::RemoteContext> RemoteBlobImpl::getContext() const noexcept {
return m_context;
}
void RemoteBlobImpl::reinterpret(const cldnn::layout& new_layout) {
OPENVINO_ASSERT(m_memory_object->size() >= new_layout.bytes_count(),
"[GPU] Can't reinterpret blob to the size bigger than allocated memory buffer",
" (", m_memory_object->size(), " vs ", new_layout.bytes_count(), ")");
m_layout = new_layout;
}
void RemoteBlobImpl::lock() const {
if (!is_allocated()) {
OPENVINO_THROW("[GPU] Remote blob can't be locked as it's not allocated");
}
std::lock_guard<std::mutex> locker(lockedMutex);
if (lockedCounter == 0) {
lockedHolder = std::unique_ptr<cldnn::mem_lock<uint8_t>>(new cldnn::mem_lock<uint8_t>(m_memory_object, m_stream));
auto ptr = lockedHolder->data();
_handle = reinterpret_cast<void*>(ptr);
auto casted_allocator = std::dynamic_pointer_cast<RemoteAllocator>(m_allocator);
OPENVINO_ASSERT(casted_allocator, "[GPU] Invalid remote allocator type");
casted_allocator->regLockedBlob(_handle, this);
}
lockedCounter++;
}
void RemoteBlobImpl::unlock() const {
std::lock_guard<std::mutex> locker(lockedMutex);
lockedCounter--;
if (lockedCounter == 0)
lockedHolder.reset();
}
LockedMemory<void> RemoteBlobImpl::buffer() noexcept {
try {
lock();
return LockedMemory<void>(m_allocator.get(), _handle, 0);
} catch (...) {
return LockedMemory<void>(nullptr, nullptr, 0);
}
}
LockedMemory<const void> RemoteBlobImpl::cbuffer() const noexcept {
try {
lock();
return LockedMemory<const void>(m_allocator.get(), _handle, 0);
} catch (...) {
return LockedMemory<const void>(nullptr, nullptr, 0);
}
}
LockedMemory<void> RemoteBlobImpl::rwmap() noexcept {
try {
lock();
return LockedMemory<void>(m_allocator.get(), _handle, 0);
} catch (...) {
return LockedMemory<void>(nullptr, nullptr, 0);
}
}
LockedMemory<const void> RemoteBlobImpl::rmap() const noexcept {
try {
lock();
return LockedMemory<const void>(m_allocator.get(), _handle, 0);
} catch (...) {
return LockedMemory<const void>(nullptr, nullptr, 0);
}
}
LockedMemory<void> RemoteBlobImpl::wmap() noexcept {
try {
lock();
return LockedMemory<void>(m_allocator.get(), _handle, 0);
} catch (...) {
return LockedMemory<void>(nullptr, nullptr, 0);
}
}
bool RemoteBlobImpl::is_shared() const {
return m_mem_type == BlobType::BT_BUF_SHARED ||
m_mem_type == BlobType::BT_USM_SHARED ||
m_mem_type == BlobType::BT_IMG_SHARED ||
m_mem_type == BlobType::BT_SURF_SHARED ||
m_mem_type == BlobType::BT_DX_BUF_SHARED;
}
bool RemoteBlobImpl::supports_caching() const {
return is_shared();
}
} // namespace intel_gpu
} // namespace ov
@@ -2,118 +2,186 @@
// SPDX-License-Identifier: Apache-2.0
//
#include <memory>
#include "openvino/runtime/intel_gpu/remote_properties.hpp"
#include "openvino/runtime/make_tensor.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/remote_blob.hpp"
#include "intel_gpu/plugin/remote_tensor.hpp"
#include "intel_gpu/plugin/remote_allocators.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include "intel_gpu/runtime/device_query.hpp"
using namespace InferenceEngine;
using namespace InferenceEngine::gpu;
using namespace InferenceEngine::details;
#include <memory>
namespace ov {
namespace intel_gpu {
RemoteContextImpl::RemoteContextImpl(std::string device_name, std::vector<cldnn::device::ptr> devices)
: m_va_display(nullptr)
, m_external_queue(nullptr)
, m_type(ContextType::OCL)
, m_device_name(std::move(device_name))
, m_memory_cache(cache_capacity) {
namespace {
template <typename Type>
Type extract_object(const ov::AnyMap& params, const ov::Property<Type>& p) {
auto itrHandle = params.find(p.name());
OPENVINO_ASSERT(itrHandle != params.end(), "[GPU] No parameter ", p.name(), " found in parameters map");
ov::Any res = itrHandle->second;
return res.as<Type>();
}
} // namespace
RemoteContextImpl::RemoteContextImpl(const std::string& device_name, std::vector<cldnn::device::ptr> devices) : m_device_name(device_name) {
OPENVINO_ASSERT(devices.size() == 1, "[GPU] Currently context can be created for single device only");
// TODO: Parameterize this based on plugin config and compilation options
auto engine_type = cldnn::engine_types::ocl;
auto runtime_type = cldnn::runtime_types::ocl;
const auto engine_type = cldnn::engine_types::ocl;
const auto runtime_type = cldnn::runtime_types::ocl;
m_engine = cldnn::engine::create(engine_type, runtime_type, devices.front());
GPU_DEBUG_LOG << "Initialize RemoteContext for " << m_device_name << " (" << m_engine->get_device_info().dev_name << ")" << std::endl;
init_properties();
}
RemoteContextImpl::RemoteContextImpl(const std::vector<RemoteContextImpl::Ptr>& known_contexts, const AnyMap& params)
: m_va_display(nullptr)
, m_external_queue(nullptr)
, m_type(ContextType::OCL)
, m_memory_cache(cache_capacity) {
gpu_handle_param _context_id = nullptr;
gpu_handle_param _va_device = nullptr;
RemoteContextImpl::RemoteContextImpl(const std::map<std::string, RemoteContextImpl::Ptr>& known_contexts, const AnyMap& params) {
gpu_handle_param context_id = nullptr;
int ctx_device_id = 0;
int target_tile_id = -1;
if (params.size()) {
// parameter map is non-empty
std::string contextTypeStr = extract_object<std::string>(params, GPU_PARAM_KEY(CONTEXT_TYPE));
auto ctx_type = extract_object(params, ov::intel_gpu::context_type);
if (GPU_PARAM_VALUE(OCL) == contextTypeStr) {
_context_id = extract_object<gpu_handle_param>(params, GPU_PARAM_KEY(OCL_CONTEXT));
if (ctx_type == ov::intel_gpu::ContextType::OCL) {
context_id = extract_object(params, ov::intel_gpu::ocl_context);
OPENVINO_ASSERT(context_id != nullptr, "[GPU] Can't create shared OCL context as user handle is nullptr! Params:\n", params);
if (params.find(GPU_PARAM_KEY(OCL_QUEUE)) != params.end())
m_external_queue = extract_object<gpu_handle_param>(params, GPU_PARAM_KEY(OCL_QUEUE));
if (params.find(ov::intel_gpu::ocl_queue.name()) != params.end()) {
m_external_queue = extract_object(params, ov::intel_gpu::ocl_queue);
}
if (params.find(GPU_PARAM_KEY(OCL_CONTEXT_DEVICE_ID)) != params.end())
ctx_device_id = extract_object<int>(params, GPU_PARAM_KEY(OCL_CONTEXT_DEVICE_ID));
} else if (GPU_PARAM_VALUE(VA_SHARED) == contextTypeStr) {
m_va_display = _va_device = extract_object<gpu_handle_param>(params, GPU_PARAM_KEY(VA_DEVICE));
m_type = ContextType::DEV_SHARED;
if (params.find(ov::intel_gpu::ocl_context_device_id.name()) != params.end())
ctx_device_id = extract_object(params, ov::intel_gpu::ocl_context_device_id);
} else if (ctx_type == ov::intel_gpu::ContextType::VA_SHARED) {
m_va_display = extract_object(params, ov::intel_gpu::va_device);
OPENVINO_ASSERT(m_va_display != nullptr, "[GPU] Can't create shared VA/DX context as user handle is nullptr! Params:\n", params);
m_type = ContextType::VA_SHARED;
} else {
OPENVINO_THROW("Invalid execution context type", contextTypeStr);
OPENVINO_THROW("Invalid execution context type", ctx_type);
}
auto tile_id_itr = params.find(GPU_PARAM_KEY(TILE_ID));
if (tile_id_itr != params.end()) {
target_tile_id = tile_id_itr->second.as<int>();
if (params.find(ov::intel_gpu::tile_id.name()) != params.end()) {
target_tile_id = extract_object(params, ov::intel_gpu::tile_id);
}
}
// TODO: Parameterize this based on plugin config and compilation options
auto engine_type = cldnn::engine_types::ocl;
auto runtime_type = cldnn::runtime_types::ocl;
const auto engine_type = cldnn::engine_types::ocl;
const auto runtime_type = cldnn::runtime_types::ocl;
// Use actual runtime and engine types
cldnn::device_query device_query(engine_type, runtime_type, _context_id, _va_device, ctx_device_id, target_tile_id);
cldnn::device_query device_query(engine_type, runtime_type, context_id, m_va_display, ctx_device_id, target_tile_id);
auto device_map = device_query.get_available_devices();
OPENVINO_ASSERT(device_map.size() == 1, "[GPU] Only one device expected in case of context sharing");
OPENVINO_ASSERT(device_map.size() == 1, "[GPU] Exactly one device expected in case of context sharing, but ", device_map.size(), " found");
m_engine = cldnn::engine::create(engine_type, runtime_type, device_map.begin()->second);
m_device_name = get_device_name(known_contexts, m_engine->get_device());
GPU_DEBUG_LOG << "Initialize RemoteContext for " << m_device_name << " (" << m_engine->get_device_info().dev_name << ")" << std::endl;
init_properties();
}
AnyMap RemoteContextImpl::get_params() const {
AnyMap ret = { { GPU_PARAM_KEY(OCL_CONTEXT), m_engine->get_user_context() } };
void RemoteContextImpl::init_properties() {
properties = { ov::intel_gpu::ocl_context(m_engine->get_user_context()) };
switch (m_type) {
case OCL:
ret[GPU_PARAM_KEY(CONTEXT_TYPE)] = GPU_PARAM_VALUE(OCL);
ret[GPU_PARAM_KEY(OCL_QUEUE)] = static_cast<gpu_handle_param>(m_external_queue);
case ContextType::OCL:
properties.insert(ov::intel_gpu::context_type(ov::intel_gpu::ContextType::OCL));
properties.insert(ov::intel_gpu::ocl_queue(m_external_queue));
break;
case DEV_SHARED:
ret[GPU_PARAM_KEY(CONTEXT_TYPE)] = GPU_PARAM_VALUE(VA_SHARED);
ret[GPU_PARAM_KEY(VA_DEVICE)] = m_va_display;
case ContextType::VA_SHARED:
properties.insert(ov::intel_gpu::context_type(ov::intel_gpu::ContextType::VA_SHARED));
properties.insert(ov::intel_gpu::va_device(m_va_display));
break;
default:
OPENVINO_THROW("Unsupported shared context type ", m_type);
OPENVINO_THROW("[GPU] Unsupported shared context type ", m_type);
}
}
return ret;
const ov::AnyMap& RemoteContextImpl::get_property() const {
return properties;
}
std::shared_ptr<RemoteContextImpl> RemoteContextImpl::get_this_shared_ptr() {
return std::static_pointer_cast<RemoteContextImpl>(shared_from_this());
}
ov::SoPtr<ov::ITensor> RemoteContextImpl::create_host_tensor(const ov::element::Type type, const ov::Shape& shape) {
if (m_engine->use_unified_shared_memory()) {
USMHostAllocator allocator(get_this_shared_ptr());
return { ov::make_tensor(type, shape, allocator), nullptr };
} else {
return { ov::make_tensor(type, shape), nullptr };
}
}
ov::SoPtr<ov::IRemoteTensor> RemoteContextImpl::create_tensor(const ov::element::Type& type, const ov::Shape& shape, const ov::AnyMap& params) {
if (params.empty()) {
// user wants plugin to allocate tensor by itself and return handle
return { create_buffer(type, shape), nullptr };
} else {
// user will supply shared object handle
auto mem_type = extract_object(params, ov::intel_gpu::shared_mem_type);
bool is_usm = mem_type == ov::intel_gpu::SharedMemType::USM_HOST_BUFFER ||
mem_type == ov::intel_gpu::SharedMemType::USM_DEVICE_BUFFER ||
mem_type == ov::intel_gpu::SharedMemType::USM_USER_BUFFER;
OPENVINO_ASSERT(!is_usm || m_engine->use_unified_shared_memory(),
"[GPU] Can't create USM tensor as USM is not supported (or manually disabled) on current device");
if (ov::intel_gpu::SharedMemType::VA_SURFACE == mem_type) {
check_if_shared();
return { reuse_surface(type, shape, params), nullptr };
} else if (ov::intel_gpu::SharedMemType::USM_HOST_BUFFER == mem_type) {
return { create_usm(type, shape, TensorType::BT_USM_HOST_INTERNAL), nullptr };
} else if (ov::intel_gpu::SharedMemType::USM_DEVICE_BUFFER == mem_type) {
return { create_usm(type, shape, TensorType::BT_USM_DEVICE_INTERNAL), nullptr };
} else {
TensorType tensor_type;
cldnn::shared_handle mem = nullptr;
if (ov::intel_gpu::SharedMemType::OCL_BUFFER == mem_type) {
tensor_type = TensorType::BT_BUF_SHARED;
mem = extract_object(params, ov::intel_gpu::mem_handle);
} else if (ov::intel_gpu::SharedMemType::USM_USER_BUFFER == mem_type) {
tensor_type = TensorType::BT_USM_SHARED;
mem = extract_object(params, ov::intel_gpu::mem_handle);
} else if (ov::intel_gpu::SharedMemType::OCL_IMAGE2D == mem_type) {
tensor_type = TensorType::BT_IMG_SHARED;
mem = extract_object(params, ov::intel_gpu::mem_handle);
#ifdef _WIN32
} else if (ov::intel_gpu::SharedMemType::DX_BUFFER == mem_type) {
tensor_type = TensorType::BT_DX_BUF_SHARED;
mem = extract_object(params, ov::intel_gpu::dev_object_handle);
check_if_shared();
#endif
} else {
OPENVINO_THROW("[GPU] Unsupported shared object type ", mem_type);
}
return { reuse_memory(type, shape, mem, tensor_type), nullptr };
}
}
}
// For external contexts we try to match underlying handles with default contexts created by plugin to find device name
std::string RemoteContextImpl::get_device_name(const std::vector<RemoteContextImpl::Ptr>& known_contexts,
const cldnn::device::ptr current_device) {
std::string RemoteContextImpl::get_device_name(const std::map<std::string, RemoteContextImpl::Ptr>& known_contexts,
const cldnn::device::ptr current_device) const {
std::string device_name = "GPU";
for (auto& c : known_contexts) {
if (c->get_engine().get_device()->is_same(current_device)) {
device_name = c->get_device_name();
if (c.second->get_engine().get_device()->is_same(current_device)) {
device_name = c.second->get_device_name();
break;
}
}
return device_name;
}
std::string RemoteContextImpl::get_device_name() const noexcept {
const std::string& RemoteContextImpl::get_device_name() const {
return m_device_name;
}
@@ -130,161 +198,35 @@ void RemoteContextImpl::add_to_cache(size_t hash, cldnn::memory::ptr memory) {
m_memory_cache.add(hash, memory);
}
InferenceEngine::RemoteBlob::Ptr RemoteContextImpl::reuse_surface(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
const InferenceEngine::ParamMap& params) {
using namespace InferenceEngine;
auto& stream = m_engine->get_service_stream();
uint32_t plane = extract_object<uint32_t>(params, GPU_PARAM_KEY(VA_PLANE));
std::shared_ptr<ov::IRemoteTensor> RemoteContextImpl::reuse_surface(const ov::element::Type type, const ov::Shape& shape, const ov::AnyMap& params) {
uint32_t plane = extract_object(params, ov::intel_gpu::va_plane);
#ifdef _WIN32
cldnn::shared_handle surf = extract_object<cldnn::shared_handle>(params, GPU_PARAM_KEY(DEV_OBJECT_HANDLE));
cldnn::shared_handle surf = extract_object(params, ov::intel_gpu::dev_object_handle);
return std::make_shared<RemoteTensorImpl>(get_this_shared_ptr(), shape, type, TensorType::BT_SURF_SHARED, surf, 0, plane);
#else
cldnn::shared_surface surf = extract_object<cldnn::shared_surface>(params, GPU_PARAM_KEY(DEV_OBJECT_HANDLE));
cldnn::shared_surface surf = extract_object(params, ov::intel_gpu::dev_object_handle);
return std::make_shared<RemoteTensorImpl>(get_this_shared_ptr(), shape, type, TensorType::BT_SURF_SHARED, nullptr, surf, plane);
#endif
cldnn::layout layout(DataTypeFromPrecision(desc.getPrecision()),
ImageFormatFromLayout(desc.getLayout()),
tensor_from_dims(desc.getDims()));
#ifdef _WIN32
auto blob = std::make_shared<RemoteD3DSurface>(public_context, stream,
desc, layout, surf, 0, plane,
BlobType::BT_SURF_SHARED);
#else
auto blob = std::make_shared<RemoteVASurface>(public_context, stream,
desc, layout, nullptr, surf, plane,
BlobType::BT_SURF_SHARED);
#endif
return blob;
}
InferenceEngine::RemoteBlob::Ptr RemoteContextImpl::reuse_memory(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
cldnn::shared_handle mem,
BlobType blob_type) {
auto& stream = m_engine->get_service_stream();
cldnn::layout layout(DataTypeFromPrecision(desc.getPrecision()),
FormatFromLayout(desc.getLayout()),
tensor_from_dims(desc.getDims()));
switch (blob_type) {
case BlobType::BT_BUF_SHARED: {
return std::make_shared<RemoteCLbuffer>(public_context, stream, desc, layout, mem, 0, 0, blob_type);
}
case BlobType::BT_USM_SHARED: {
return std::make_shared<RemoteUSMbuffer>(public_context, stream, desc, layout, mem, 0, 0, blob_type);
}
case BlobType::BT_IMG_SHARED: {
layout.format = ImageFormatFromLayout(desc.getLayout());
return std::make_shared<RemoteCLImage2D>(public_context, stream, desc, layout, mem, 0, 0, blob_type);
}
#ifdef _WIN32
case BlobType::BT_DX_BUF_SHARED: {
return std::make_shared<RemoteD3DBuffer>(public_context, stream, desc, layout, mem, 0, 0, blob_type);
}
#endif
default:
break;
}
return nullptr;
std::shared_ptr<ov::IRemoteTensor> RemoteContextImpl::reuse_memory(const ov::element::Type type,
const ov::Shape& shape,
cldnn::shared_handle mem,
TensorType tensor_type) {
return std::make_shared<RemoteTensorImpl>(get_this_shared_ptr(), shape, type, tensor_type, mem);
}
InferenceEngine::RemoteBlob::Ptr RemoteContextImpl::create_buffer(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc) {
cldnn::layout layout(DataTypeFromPrecision(desc.getPrecision()),
FormatFromLayout(desc.getLayout()),
tensor_from_dims(desc.getDims()));
auto& stream = m_engine->get_service_stream();
return std::make_shared<RemoteCLbuffer>(public_context,
stream,
desc,
layout,
nullptr, 0, 0,
BlobType::BT_BUF_INTERNAL);
std::shared_ptr<ov::IRemoteTensor> RemoteContextImpl::create_buffer(const ov::element::Type type, const ov::Shape& shape) {
return std::make_shared<RemoteTensorImpl>(get_this_shared_ptr(), shape, type, TensorType::BT_BUF_INTERNAL);
}
InferenceEngine::RemoteBlob::Ptr RemoteContextImpl::create_usm(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
BlobType alloc_type) {
cldnn::layout layout(DataTypeFromPrecision(desc.getPrecision()),
FormatFromLayout(desc.getLayout()),
tensor_from_dims(desc.getDims()));
auto& stream = m_engine->get_service_stream();
return std::make_shared<RemoteUSMbuffer>(public_context,
stream,
desc,
layout,
nullptr, 0, 0,
alloc_type);
std::shared_ptr<ov::IRemoteTensor> RemoteContextImpl::create_usm(const ov::element::Type type, const ov::Shape& shape, TensorType alloc_type) {
return std::make_shared<RemoteTensorImpl>(get_this_shared_ptr(), shape, type, alloc_type);
}
void RemoteContextImpl::check_if_shared() {
OPENVINO_ASSERT(m_type == RemoteContextImpl::ContextType::DEV_SHARED, "[GPU] Shared context is required to to share this type of memory");
}
InferenceEngine::MemoryBlob::Ptr RemoteContextImpl::create_host_blob(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc) {
if (m_engine->use_unified_shared_memory())
return std::dynamic_pointer_cast<InferenceEngine::MemoryBlob>(make_blob_with_precision(desc, std::make_shared<USMHostAllocator>(public_context)));
else
return std::dynamic_pointer_cast<InferenceEngine::MemoryBlob>(make_blob_with_precision(desc));
}
InferenceEngine::RemoteBlob::Ptr RemoteContextImpl::create_blob(InferenceEngine::gpu::ClContext::Ptr public_context,
const InferenceEngine::TensorDesc& desc,
const InferenceEngine::ParamMap& params) {
using namespace InferenceEngine;
if (params.empty()) {
// user wants plugin to allocate blob by itself and return handle
return create_buffer(public_context, desc);
} else {
// user will supply shared object handle
std::string mem_type = extract_object<std::string>(params, GPU_PARAM_KEY(SHARED_MEM_TYPE));
bool is_usm = mem_type == GPU_PARAM_VALUE(USM_HOST_BUFFER) ||
mem_type == GPU_PARAM_VALUE(USM_DEVICE_BUFFER) ||
mem_type == GPU_PARAM_VALUE(USM_USER_BUFFER);
OPENVINO_ASSERT(!is_usm || m_engine->use_unified_shared_memory(),
"[GPU] Can't create USM tensor as USM is not supported (or manually disabled) on current device");
if (GPU_PARAM_VALUE(VA_SURFACE) == mem_type) {
check_if_shared();
return reuse_surface(public_context, desc, params);
} else if (GPU_PARAM_VALUE(USM_HOST_BUFFER) == mem_type) {
return create_usm(public_context, desc, BlobType::BT_USM_HOST_INTERNAL);
} else if (GPU_PARAM_VALUE(USM_DEVICE_BUFFER) == mem_type) {
return create_usm(public_context, desc, BlobType::BT_USM_DEVICE_INTERNAL);
} else {
BlobType blob_type;
cldnn::shared_handle mem = nullptr;
if (GPU_PARAM_VALUE(OCL_BUFFER) == mem_type) {
blob_type = BlobType::BT_BUF_SHARED;
mem = extract_object<cldnn::shared_handle>(params, GPU_PARAM_KEY(MEM_HANDLE));
} else if (GPU_PARAM_VALUE(USM_USER_BUFFER) == mem_type) {
blob_type = BlobType::BT_USM_SHARED;
mem = extract_object<cldnn::shared_handle>(params, GPU_PARAM_KEY(MEM_HANDLE));
} else if (GPU_PARAM_VALUE(OCL_IMAGE2D) == mem_type) {
blob_type = BlobType::BT_IMG_SHARED;
mem = extract_object<cldnn::shared_handle>(params, GPU_PARAM_KEY(MEM_HANDLE));
#ifdef _WIN32
} else if (GPU_PARAM_VALUE(DX_BUFFER) == mem_type) {
blob_type = BlobType::BT_DX_BUF_SHARED;
mem = extract_object<cldnn::shared_handle>(params, GPU_PARAM_KEY(DEV_OBJECT_HANDLE));
check_if_shared();
#endif
} else {
OPENVINO_ASSERT(false, "[GPU] Unsupported shared object type ", mem_type);
}
return reuse_memory(public_context, desc, mem, blob_type);
}
}
void RemoteContextImpl::check_if_shared() const {
OPENVINO_ASSERT(m_type == ContextType::VA_SHARED, "[GPU] Shared context is required to to share this type of memory");
}
} // namespace intel_gpu
@@ -0,0 +1,272 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/remote_tensor.hpp"
#include "intel_gpu/plugin/remote_allocators.hpp"
#include "intel_gpu/plugin/plugin.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include <memory>
namespace ov {
namespace intel_gpu {
RemoteTensorImpl::RemoteTensorImpl(RemoteContextImpl::Ptr context,
const ov::Shape& shape,
const ov::element::Type& element_type,
TensorType mem_type,
cldnn::shared_handle mem,
cldnn::shared_surface surf,
uint32_t plane)
: m_context(context)
, m_element_type(element_type)
, m_shape(shape)
, m_layout(make_layout(element_type, shape))
, m_mem_type(mem_type)
, m_mem(mem)
, m_surf(surf)
, m_plane(plane) {
if (supports_caching()) {
m_hash = cldnn::hash_combine(0, m_mem);
m_hash = cldnn::hash_combine(m_hash, m_surf);
m_hash = cldnn::hash_combine(m_hash, plane);
m_hash = cldnn::hash_combine(m_hash, m_shape.size());
m_hash = cldnn::hash_combine(m_hash, element_type.hash());
for (const auto& d : m_shape) {
m_hash = cldnn::hash_combine(m_hash, d);
}
}
update_strides();
allocate();
init_properties();
}
RemoteTensorImpl::~RemoteTensorImpl() {
deallocate();
}
const ov::element::Type& RemoteTensorImpl::get_element_type() const {
return m_element_type;
}
const ov::Shape& RemoteTensorImpl::get_shape() const {
return m_shape;
}
void RemoteTensorImpl::update_strides() {
if (m_element_type.bitwidth() < 8)
return;
auto& shape = get_shape();
m_strides.clear();
if (!shape.empty()) {
m_strides.resize(shape.size());
m_strides.back() = m_element_type.size();
std::copy(shape.rbegin(), shape.rend() - 1, m_strides.rbegin() + 1);
std::partial_sum(m_strides.rbegin(), m_strides.rend(), m_strides.rbegin(), std::multiplies<size_t>());
}
}
const ov::Strides& RemoteTensorImpl::get_strides() const {
return m_strides;
}
const AnyMap& RemoteTensorImpl::get_properties() const {
return m_properties;
}
void RemoteTensorImpl::set_shape(ov::Shape shape) {
m_layout.set_partial_shape(ov::PartialShape{shape});
m_shape = shape;
if (ov::shape_size(shape) > m_memory_object->count()) {
OPENVINO_ASSERT(!is_shared(), "Cannot call setShape for Tensor created on top of preallocated memory if shape was increased.");
if (!deallocate()) {
OPENVINO_THROW("Cannot deallocate tensor while an attempt to enlarge tensor area in setShape.");
}
allocate();
}
}
bool RemoteTensorImpl::deallocate() noexcept {
m_memory_object.reset();
return m_memory_object == nullptr;
}
bool RemoteTensorImpl::is_allocated() const noexcept {
return m_memory_object != nullptr;
}
void RemoteTensorImpl::allocate() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "RemoteTensorImpl::Allocate");
auto context = std::dynamic_pointer_cast<RemoteContextImpl>(m_context);
auto enable_caching = supports_caching();
if (enable_caching) {
m_memory_object = context->try_get_cached_memory(m_hash);
if (m_memory_object)
return;
}
auto& engine = context->get_engine();
switch (m_mem_type) {
case TensorType::BT_BUF_INTERNAL: {
m_memory_object = engine.allocate_memory(m_layout, cldnn::allocation_type::cl_mem);
break;
}
case TensorType::BT_USM_HOST_INTERNAL: {
m_memory_object = engine.allocate_memory(m_layout, cldnn::allocation_type::usm_host);
break;
}
case TensorType::BT_USM_DEVICE_INTERNAL: {
m_memory_object = engine.allocate_memory(m_layout, cldnn::allocation_type::usm_device);
break;
}
case TensorType::BT_BUF_SHARED: {
m_memory_object = engine.share_buffer(m_layout, m_mem);
break;
}
case TensorType::BT_USM_SHARED: {
m_memory_object = engine.share_usm(m_layout, m_mem);
break;
}
#ifdef _WIN32
case TensorType::BT_SURF_SHARED: {
m_layout.format = cldnn::format::nv12; // Other formats are not supported
m_memory_object = engine.share_surface(m_layout, m_mem, m_plane);
break;
}
case TensorType::BT_DX_BUF_SHARED: {
m_memory_object = engine.share_dx_buffer(m_layout, m_mem);
break;
}
#else
case TensorType::BT_SURF_SHARED: {
m_layout.format = cldnn::format::nv12; // Other formats are not supported
m_memory_object = engine.share_surface(m_layout, m_surf, m_plane);
break;
}
#endif
case TensorType::BT_IMG_SHARED: {
m_layout.format = cldnn::format::nv12; // Other formats are not supported
m_memory_object = engine.share_image(m_layout, m_mem);
break;
}
default:
m_memory_object.reset();
}
if (enable_caching)
context->add_to_cache(m_hash, m_memory_object);
}
const std::string& RemoteTensorImpl::get_device_name() const {
return m_context->get_device_name();
}
bool RemoteTensorImpl::is_shared() const {
return m_mem_type == TensorType::BT_BUF_SHARED ||
m_mem_type == TensorType::BT_USM_SHARED ||
m_mem_type == TensorType::BT_IMG_SHARED ||
m_mem_type == TensorType::BT_SURF_SHARED ||
m_mem_type == TensorType::BT_DX_BUF_SHARED;
}
bool RemoteTensorImpl::supports_caching() const {
return is_shared();
}
bool RemoteTensorImpl::is_surface() const noexcept {
return m_mem_type == TensorType::BT_SURF_SHARED ||
m_mem_type == TensorType::BT_IMG_SHARED ||
m_mem_type == TensorType::BT_DX_BUF_SHARED;
}
cldnn::memory::ptr RemoteTensorImpl::get_memory() const {
auto engine = m_memory_object->get_engine();
return engine->reinterpret_buffer(*m_memory_object, m_layout);
}
cldnn::memory::ptr RemoteTensorImpl::get_original_memory() const {
return m_memory_object;
}
std::shared_ptr<RemoteContextImpl> RemoteTensorImpl::get_context() const {
return m_context;
}
void RemoteTensorImpl::init_properties() {
OPENVINO_ASSERT(is_allocated(), "[GPU] Can't initialize RemoteTensorImpl parameters as memory was not allocated");
auto params = m_memory_object->get_internal_params();
switch (m_mem_type) {
case TensorType::BT_BUF_INTERNAL:
case TensorType::BT_BUF_SHARED:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::OCL_BUFFER),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::mem_handle(params.mem),
};
break;
case TensorType::BT_USM_SHARED:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::USM_USER_BUFFER),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::mem_handle(params.mem),
};
break;
case TensorType::BT_USM_HOST_INTERNAL:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::USM_HOST_BUFFER),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::mem_handle(params.mem),
};
break;
case TensorType::BT_USM_DEVICE_INTERNAL:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::USM_DEVICE_BUFFER),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::mem_handle(params.mem),
};
break;
#ifdef _WIN32
case TensorType::BT_DX_BUF_SHARED:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::DX_BUFFER),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::va_device(params.user_device),
ov::intel_gpu::mem_handle(params.mem),
ov::intel_gpu::dev_object_handle(params.surface),
};
break;
#endif
case TensorType::BT_IMG_SHARED:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::OCL_IMAGE2D),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::mem_handle(params.mem),
};
break;
case TensorType::BT_SURF_SHARED:
m_properties = {
ov::intel_gpu::shared_mem_type(ov::intel_gpu::SharedMemType::VA_SURFACE),
ov::intel_gpu::ocl_context(params.context),
ov::intel_gpu::va_device(params.user_device),
ov::intel_gpu::mem_handle(params.mem),
ov::intel_gpu::dev_object_handle(params.surface),
ov::intel_gpu::va_plane(params.plane),
};
break;
default:
OPENVINO_THROW("[GPU] Unsupported shared object type ", static_cast<int>(m_mem_type));
}
}
} // namespace intel_gpu
} // namespace ov
@@ -0,0 +1,815 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/runtime/make_tensor.hpp"
#include "openvino/core/preprocess/input_tensor_info.hpp"
#include "openvino/core/parallel.hpp"
#include "openvino/op/util/op_types.hpp"
#include "transformations/utils/utils.hpp"
#include "intel_gpu/plugin/sync_infer_request.hpp"
#include "intel_gpu/plugin/remote_context.hpp"
#include "intel_gpu/plugin/remote_allocators.hpp"
#include "intel_gpu/plugin/remote_tensor.hpp"
#include "intel_gpu/plugin/compiled_model.hpp"
#include "intel_gpu/plugin/variable_state.hpp"
#include "intel_gpu/runtime/internal_properties.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include "intel_gpu/runtime/debug_configuration.hpp"
#include <algorithm>
#include <iterator>
#include <memory>
#include <string>
#include <map>
#include <functional>
#include <utility>
namespace {
inline std::string get_port_name(const ov::Output<const ov::Node>& port, const bool is_legacy_api) {
std::string name;
// TODO: Should use tensor name as the port name, but many legacy tests still use legacy name
// plus sometimes it will get empty tensor name.
if (!is_legacy_api) {
name = {};
}
if (name.empty()) {
bool is_input = ov::op::util::is_parameter(port.get_node());
if (is_input) {
name = ov::op::util::get_ie_output_name(port);
} else {
const auto node = port.get_node_shared_ptr();
name = ov::op::util::get_ie_output_name(node->input_value(0));
}
}
return name;
}
template <typename src_t, typename dst_t>
void convert_any_copy(const src_t* src, dst_t* dst, size_t size) {
OPENVINO_ASSERT(src && dst, "[GPU] Src or Dst ptr is null");
for (size_t i = 0; i < size; i++)
dst[i] = static_cast<dst_t>(src[i]);
}
void convert_and_copy(const void* src_ptr, ov::element::Type src_et, void* dst_ptr, ov::element::Type dst_et, size_t size) {
if (size == 0)
return;
if (src_et == dst_et) {
std::memcpy(dst_ptr, src_ptr, size);
return;
}
#define CASE(s_et, d_et, s_type, d_type) \
if (src_et == s_et && dst_et == d_et) return convert_any_copy(static_cast<const s_type*>(src_ptr), static_cast<d_type*>(dst_ptr), size)
// For unsupported inputs
CASE(ov::element::f64, ov::element::f32, double, float);
CASE(ov::element::i16, ov::element::f32, int16_t, float);
CASE(ov::element::u16, ov::element::f32, uint16_t, float);
CASE(ov::element::u64, ov::element::i32, uint64_t, int32_t);
CASE(ov::element::i64, ov::element::i32, int64_t, int32_t);
CASE(ov::element::u32, ov::element::i32, uint32_t, int32_t);
// For unsupported outputs
CASE(ov::element::f32, ov::element::f64, float, double);
CASE(ov::element::i32, ov::element::i64, int32_t, int64_t);
CASE(ov::element::i32, ov::element::u64, int32_t, uint64_t);
CASE(ov::element::i32, ov::element::u32, int32_t, uint32_t);
CASE(ov::element::f32, ov::element::i16, float, int16_t);
CASE(ov::element::f32, ov::element::u16, float, uint16_t);
// TODO: Need instances below?
CASE(ov::element::u32, ov::element::i64, uint32_t, int64_t);
CASE(ov::element::u32, ov::element::u64, uint32_t, uint64_t);
OPENVINO_THROW("[GPU] Unsupported element types combination for copy: ", src_et, " -> ", dst_et);
}
bool is_convert_required(ov::element::Type src_et, ov::element::Type dst_et) {
return src_et != dst_et && !(dst_et == ov::element::boolean && src_et == ov::element::u8);
}
void convert_and_copy(const cldnn::memory::ptr src, ov::ITensor const* dst, const cldnn::stream& stream) {
auto src_et = cldnn::data_type_to_element_type(src->get_layout().data_type);
auto dst_et = dst->get_element_type();
size_t size = ov::shape_size(dst->get_shape());
cldnn::mem_lock<uint8_t> src_lock(src, stream);
std::unique_ptr<cldnn::mem_lock<uint8_t>> dst_lock = nullptr;
const void* src_ptr = src_lock.data();
void* dst_ptr = nullptr;
if (auto remote = dynamic_cast<const ov::intel_gpu::RemoteTensorImpl*>(dst)) {
auto mem = remote->get_original_memory();
dst_lock.reset(new cldnn::mem_lock<uint8_t>(mem, stream));
dst_ptr = dst_lock->data();
} else {
dst_ptr = dst->data();
}
return convert_and_copy(src_ptr, src_et, dst_ptr, dst_et, size);
}
void convert_and_copy(const ov::ITensor* src, ov::ITensor const* dst, const cldnn::stream& stream) {
auto src_et = src->get_element_type();
auto dst_et = dst->get_element_type();
size_t size = ov::shape_size(dst->get_shape());
const void* src_ptr = nullptr;
void* dst_ptr = nullptr;
std::unique_ptr<cldnn::mem_lock<uint8_t>> src_lock = nullptr;
std::unique_ptr<cldnn::mem_lock<uint8_t>> dst_lock = nullptr;
if (auto remote = dynamic_cast<const ov::intel_gpu::RemoteTensorImpl*>(src)) {
auto mem = remote->get_original_memory();
src_lock.reset(new cldnn::mem_lock<uint8_t>(mem, stream));
src_ptr = src_lock->data();
} else {
src_ptr = src->data();
}
if (auto remote = dynamic_cast<const ov::intel_gpu::RemoteTensorImpl*>(dst)) {
auto mem = remote->get_original_memory();
dst_lock.reset(new cldnn::mem_lock<uint8_t>(mem, stream));
dst_ptr = dst_lock->data();
} else {
dst_ptr = dst->data();
}
return convert_and_copy(src_ptr, src_et, dst_ptr, dst_et, size);
}
bool same_host_mem(cldnn::memory::cptr memory, const uint8_t* host_ptr) {
const uint8_t* device_ptr = memory->get_allocation_type() == cldnn::allocation_type::usm_host ?
static_cast<uint8_t*>(memory->get_internal_params().mem) : nullptr;
return device_ptr == host_ptr;
}
ov::Shape predict_shape(const std::string& name, const ov::Shape current_shape, ov::element::Type element_type, cldnn::ShapePredictor& shape_predictor) {
auto et_size = cldnn::ceil_div(element_type.bitwidth(), 8);
auto prealloc_info = shape_predictor.predict_preallocation_shape(name, current_shape, et_size, false);
const auto& preallocation_shape = prealloc_info.second;
auto can_preallocate_buffer = prealloc_info.first &&
shape_predictor.can_preallocate(ov::shape_size(preallocation_shape) * et_size);
if (can_preallocate_buffer) {
return preallocation_shape;
}
return current_shape;
}
inline bool all_remote_buffers(const std::vector<ov::SoPtr<ov::ITensor>>& tensors) {
return std::all_of(tensors.begin(), tensors.end(), [](const ov::SoPtr<ov::ITensor>& tensor) {
if (auto remote_ptr = std::dynamic_pointer_cast<ov::intel_gpu::RemoteTensorImpl>(tensor._ptr)) {
return !remote_ptr->is_surface();
}
return false;
});
}
inline bool all_remote_surfaces(const std::vector<ov::SoPtr<ov::ITensor>>& tensors) {
return std::all_of(tensors.begin(), tensors.end(), [](const ov::SoPtr<ov::ITensor>& tensor) {
if (auto remote_ptr = std::dynamic_pointer_cast<ov::intel_gpu::RemoteTensorImpl>(tensor._ptr)) {
return remote_ptr->is_surface();
}
return false;
});
}
inline bool all_host_tensors(const std::vector<ov::SoPtr<ov::ITensor>>& tensors) {
return std::all_of(tensors.begin(), tensors.end(), [](const ov::SoPtr<ov::ITensor>& tensor) {
return std::dynamic_pointer_cast<ov::intel_gpu::RemoteTensorImpl>(tensor._ptr) == nullptr;
});
}
} // namespace
namespace ov {
namespace intel_gpu {
// ----------------------------------------------------------------------------------------------- //
// ---------------------------- OpenVINO API impl ------------------------------------------------ //
// ----------------------------------------------------------------------------------------------- //
SyncInferRequest::SyncInferRequest(const std::shared_ptr<const CompiledModel>& compiled_model)
: ov::ISyncInferRequest(compiled_model)
, m_graph(compiled_model->get_graph(0))
, m_context(std::static_pointer_cast<RemoteContextImpl>(compiled_model->get_context_impl()))
, m_enable_profiling(m_graph->get_config().get_property(ov::enable_profiling))
, m_use_external_queue(m_graph->use_external_queue()) {
bool is_legacy_api = !compiled_model->is_new_api();
init_mappings(is_legacy_api);
allocate_inputs();
allocate_outputs();
allocate_states();
}
void SyncInferRequest::infer() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::infer");
setup_stream_graph();
std::lock_guard<std::mutex> lk(m_graph->get_mutex());
enqueue();
wait();
}
std::vector<ov::ProfilingInfo> SyncInferRequest::get_profiling_info() const {
OPENVINO_ASSERT(m_enable_profiling, "[GPU] Profiling data was not collected: please check that ov::enable_profiling property was set to true");
return m_graph->get_profiling_info();
}
std::vector<ov::SoPtr<ov::IVariableState>> SyncInferRequest::query_state() const {
std::vector<ov::SoPtr<ov::IVariableState>> ret{};
const auto& variable_states = m_graph->get_network()->get_variable_memories();
for (const auto& pair : variable_states) {
ret.emplace_back(std::make_shared<VariableState>(pair.first, pair.second, m_graph->get_engine()));
}
auto expected_states_count = m_graph->get_network()->get_variables_state_info().size();
OPENVINO_ASSERT(expected_states_count == ret.size(), "[GPU] Mismatch of expected states count (",
expected_states_count, ") and actual size (", ret.size(), ")");
return ret;
}
void SyncInferRequest::set_tensor(const ov::Output<const ov::Node>& port, const ov::SoPtr<ov::ITensor>& tensor) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::set_tensor");
const auto& compiled_model = std::static_pointer_cast<const CompiledModel>(get_compiled_model());
const auto name = get_port_name(port, !compiled_model->is_new_api());
const auto& shape = port.get_partial_shape();
OPENVINO_ASSERT(tensor != nullptr, "[GPU] Failed to set empty tensor to port: \'", name, "\'");
OPENVINO_ASSERT(port.get_element_type() == tensor->get_element_type(),
"[GPU] Mismtach tensor and port type: ", port.get_element_type(), " vs ", tensor->get_element_type());
OPENVINO_ASSERT(shape.compatible(ov::PartialShape(tensor->get_shape())) || tensor->get_shape() == ov::Shape{0},
"[GPU] The tensor size is not equal to model, can't set input tensor with name: ",
name,
", because model input (shape=",
shape,
") and tensor (shape=",
tensor->get_shape(),
") are incompatible");
bool is_input = ov::op::util::is_parameter(port.get_node());
if (is_input) {
m_user_inputs[name] = { tensor._ptr, TensorOwner::USER };
} else {
m_user_outputs[name] = { tensor._ptr, TensorOwner::USER };
}
ov::ISyncInferRequest::set_tensor(port, tensor);
}
void SyncInferRequest::set_tensors_impl(const ov::Output<const ov::Node> port, const std::vector<ov::SoPtr<ov::ITensor>>& tensors) {
if (tensors.size() == 1) {
return set_tensor(port, tensors[0]);
}
bool is_input = ov::op::util::is_parameter(port.get_node());
OPENVINO_ASSERT(is_input, "[GPU] set_tensors_impl is not supported for output port");
bool is_remote = all_remote_buffers(tensors) || all_remote_surfaces(tensors);
bool is_host = all_host_tensors(tensors);
OPENVINO_ASSERT(is_host || is_remote, "[GPU] Incorrect input blobs. All blobs must be of the same type");
for (const auto& input : get_inputs()) {
if (input == port) {
m_batched_tensors[input.get_tensor_ptr()] = tensors;
return;
}
}
OPENVINO_THROW("[GPU] Cannot find input tensors for port ", port);
}
ov::SoPtr<ov::ITensor> SyncInferRequest::get_tensor(const ov::Output<const ov::Node>& port) const {
bool is_input = ov::op::util::is_parameter(port.get_node());
const auto& compiled_model = std::static_pointer_cast<const CompiledModel>(get_compiled_model());
const auto name = get_port_name(port, !compiled_model->is_new_api());
if (is_input) {
OPENVINO_ASSERT(m_user_inputs.count(name) == 1, "[GPU] Input tensor with name ", name, " is not found");
return { m_user_inputs.at(name).ptr, nullptr };
} else {
OPENVINO_ASSERT(m_user_outputs.count(name) == 1, "[GPU] Output tensor with name ", name, " is not found");
return { m_user_outputs.at(name).ptr, nullptr };
}
}
void SyncInferRequest::check_tensors() const {
const auto& inputs = get_compiled_model()->inputs();
for (size_t i = 0; i < inputs.size(); i++) {
if (!is_batched_input(inputs[i]))
check_tensor(inputs[i], get_tensor_ptr(inputs[i]));
}
const auto& outputs = get_compiled_model()->outputs();
for (size_t i = 0; i < outputs.size(); i++) {
check_tensor(outputs[i], get_tensor_ptr(outputs[i]));
}
}
// ----------------------------------------------------------------------------------------- //
// ---------------------------- internal pipeline stages ----------------------------------- //
// ----------------------------------------------------------------------------------------- //
void SyncInferRequest::set_task_executor(const std::shared_ptr<ov::threading::ITaskExecutor>& task_executor) {
m_stream_executor = std::dynamic_pointer_cast<ov::threading::IStreamsExecutor>(task_executor);
}
void SyncInferRequest::enqueue_notify() {
m_graph->wait(Graph::Stage::EXECUTE);
enqueue();
}
void SyncInferRequest::wait_notify() {
wait();
m_graph->notify(Graph::Stage::EXECUTE);
}
void SyncInferRequest::enqueue() {
// set input and output memory from request blob maps
// into the network object primitives
std::vector<cldnn::event::ptr> dependencies;
for (const auto& it : m_input_ports_map) {
const auto& name = it.first;
const auto& port = it.second;
if (m_batched_tensors.count(port.get_tensor_ptr()) > 0) {
auto events = prepare_batched_input(name, port, m_batched_tensors.at(port.get_tensor_ptr()));
std::move(events.begin(), events.end(), std::back_inserter(dependencies));
} else {
auto events = prepare_input(name, port, m_user_inputs.at(name));
std::move(events.begin(), events.end(), std::back_inserter(dependencies));
}
}
for (const auto& it : m_output_ports_map) {
const auto& name = it.first;
const auto& port = it.second;
auto events = prepare_output(name, port, m_user_outputs.at(name));
std::move(events.begin(), events.end(), std::back_inserter(dependencies));
}
auto network = m_graph->get_network();
network->assign_variables_memories();
m_internal_outputs.clear();
m_internal_outputs = network->execute(dependencies);
// If dump layers path is set, only runs first inference.
GPU_DEBUG_GET_INSTANCE(debug_config);
GPU_DEBUG_IF(debug_config->dump_layers_path.length() > 0 && debug_config->dump_iteration.empty()) {
GPU_DEBUG_INFO << "Only run first inference to dump layers." << std::endl;
exit(0);
}
}
void SyncInferRequest::wait() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::wait");
OPENVINO_ASSERT(!m_internal_outputs.empty(), "[GPU] Inference was not started!\n");
// wait for completion & collect outputs as requested by the model
// for in_order_queue, it is enough to call finish only once
bool do_sync_per_output = (m_graph->get_network()->get_stream().get_queue_type() == QueueTypes::in_order) ? false : true;
if (!do_sync_per_output)
m_graph->get_network()->get_stream().finish();
std::vector<cldnn::event::ptr> copy_events;
for (const auto& it : m_output_ports_map) {
const auto& name = it.first;
const auto& port = it.second;
cldnn::primitive_id internal_name = m_output_names_map.at(name);
auto output_memory = m_internal_outputs.at(internal_name).get_memory(do_sync_per_output);
auto output_layout = m_internal_outputs.at(internal_name).get_layout();
if (output_memory) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::wait::reinterpret_memory");
OPENVINO_ASSERT(!output_memory->get_layout().data_padding, "[GPU] Unexpected padding in output buffer");
output_memory = m_graph->get_engine().reinterpret_buffer(*output_memory, output_layout);
}
OPENVINO_ASSERT(m_user_outputs.count(name) > 0, "[GPU] Output ", name, " is not found in output tensors map");
auto output_tensor_wrapper = m_user_outputs.at(name);
auto output_tensor = output_tensor_wrapper.ptr;
auto remote_ptr = std::dynamic_pointer_cast<RemoteTensorImpl>(output_tensor);
bool is_remote = remote_ptr != nullptr;
bool need_output_update = output_layout.bytes_count() == 0 || (output_memory && output_tensor->get_byte_size() != output_memory->size());
if (need_output_update) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::wait::update_output");
auto mem_shape = output_layout.get_shape();
// In case of old shape infer we need to shrink out tensor shape to avoid redudnant dimensions that occur due to rank extension
// For new shape infer this shouldn't happen, thus remove that WA once we migrate to ngraph-based shape infer for all cases
if (!m_graph->get_config().get_property(ov::intel_gpu::allow_new_shape_infer)) {
OPENVINO_ASSERT(port.get_partial_shape().is_static(), "[GPU] Unexpected dynamic shape for legacy shape inference");
OPENVINO_ASSERT(ov::shape_size(port.get_shape()) == ov::shape_size(mem_shape), "[GPU] Unexpected elements count for output tensor");
mem_shape = port.get_shape();
}
output_tensor->set_shape(mem_shape);
}
// mapping remote blobs not needed -
// let the user take care of them explicitly
if (!is_remote && output_memory) {
auto dst_ptr = static_cast<uint8_t*>(output_tensor->data());
bool same_mem = same_host_mem(output_memory, dst_ptr);
if (!same_mem && output_memory->size()) {
if (auto ev = copy_output_data(output_memory, *output_tensor)) {
copy_events.push_back(ev);
}
}
}
}
if (!copy_events.empty()) {
auto& stream = m_graph->get_network()->get_stream();
if (stream.get_queue_type() == QueueTypes::in_order) {
// wait only the last one
stream.wait_for_events({copy_events.back()});
} else {
stream.wait_for_events(copy_events);
}
}
// finally collect profiling info
if (m_enable_profiling) {
m_graph->update_profiling_info();
}
}
// ----------------------------------------------------------------------------------------- //
// ---------------------------- internal utils --------- ----------------------------------- //
// ----------------------------------------------------------------------------------------- //
void SyncInferRequest::setup_stream_graph() {
int stream_id = 0;
auto& stream_graphs = std::static_pointer_cast<const CompiledModel>(get_compiled_model())->get_graphs();
if (nullptr != m_stream_executor) {
stream_id = m_stream_executor->get_stream_id();
auto num_graphs = stream_graphs.size();
stream_id = stream_id % num_graphs;
}
m_graph = stream_graphs[stream_id];
}
std::shared_ptr<ov::ITensor> SyncInferRequest::create_host_tensor(const ov::PartialShape& port_shape, const ov::element::Type& port_element_type) const {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::create_host_tensor");
// Disable USM usage as USMHostAllocator may fail for attempt to allocate 0 bytes
// If we add WA for such case to avoid driver call, then deallocate method will return false and Blob::setShape call will throw an exception
bool use_usm = m_graph->get_engine().use_unified_shared_memory() && !port_shape.is_dynamic();
auto shape = port_shape.is_static() ? port_shape.to_shape() : ov::Shape(port_shape.size(), 0);
auto usm_allocator = USMHostAllocator(m_context);
return use_usm ? ov::make_tensor(port_element_type, shape, usm_allocator)
: ov::make_tensor(port_element_type, shape);
}
std::shared_ptr<ov::ITensor> SyncInferRequest::create_device_tensor(const ov::Shape& shape, ov::element::Type element_type,
bool need_lockable_memory, void* mem_ptr) const {
TensorType tensor_type = TensorType::BT_EMPTY;
if (mem_ptr) {
tensor_type = TensorType::BT_USM_SHARED;
} else if (m_graph->get_engine().use_unified_shared_memory()) {
tensor_type = need_lockable_memory ? TensorType::BT_USM_HOST_INTERNAL : TensorType::BT_USM_DEVICE_INTERNAL;
} else {
tensor_type = TensorType::BT_BUF_INTERNAL;
}
// Currently, clDeviceMemAllocINTEL returns memory address allocated to other input blob if the current blob is empty
// W/A for this issue:
// Allocate with non-empty shape and then reinterprete with original shape
auto shape_copy = shape;
for (auto &i : shape_copy) {
if (i == 0)
i = 1;
}
return std::make_shared<RemoteTensorImpl>(m_context,
shape_copy,
element_type,
tensor_type,
mem_ptr);
}
std::shared_ptr<ov::ITensor> SyncInferRequest::create_shared_device_tensor(const ov::Shape& shape, ov::element::Type element_type, void* usm_host_mem) const {
return create_device_tensor(shape, element_type, false, usm_host_mem);
}
TensorWrapper SyncInferRequest::create_or_share_device_tensor(const TensorWrapper& user_tensor_wrapper,
const std::string& name,
const ov::PartialShape& port_pshape,
ov::element::Type element_type,
bool need_lockable_mem) const {
auto user_tensor = user_tensor_wrapper.ptr;
auto tensor_shape = user_tensor->get_shape();
bool is_dynamic = port_pshape.is_dynamic();
OPENVINO_ASSERT(std::dynamic_pointer_cast<RemoteTensorImpl>(user_tensor) == nullptr, "[GPU] Unexpected remote tensor");
auto input_ptr = user_tensor->data();
const auto alloc_type = m_graph->get_engine().detect_usm_allocation_type(input_ptr);
const auto is_usm_host = alloc_type == cldnn::allocation_type::usm_host;
bool can_share = is_usm_host && !is_convert_required(user_tensor->get_element_type(), element_type);
if (can_share) {
// For USM case we create host blob using custom USM host allocator
// and then create shared device blob on top of this buffer
return { create_shared_device_tensor(tensor_shape, element_type, input_ptr), user_tensor_wrapper.owner };
}
auto actual_memory_shape = tensor_shape;
if (is_dynamic) {
auto& shape_predictor = m_graph->get_network()->get_shape_predictor();
actual_memory_shape = predict_shape(name, tensor_shape, element_type, shape_predictor);
}
return { create_device_tensor(actual_memory_shape, element_type, need_lockable_mem), TensorOwner::PLUGIN };
}
cldnn::event::ptr SyncInferRequest::copy_output_data(cldnn::memory::ptr src, const ov::ITensor& dst) const {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::copy_output_data");
OPENVINO_ASSERT(src->count() <= dst.get_size(),
"[GPU] Unexpected elements count of dst tensor: ",
"expected at least ", src->count(), ", but ",
"only ", dst.get_size(), " got");
const auto& layout = src->get_layout();
auto& stream = m_graph->get_network()->get_stream();
if (is_convert_required(cldnn::data_type_to_element_type(layout.data_type), dst.get_element_type())) {
convert_and_copy(src, &dst, stream);
return nullptr;
} else {
return src->copy_to(stream, dst.data(), false);
}
}
void SyncInferRequest::allocate_input(const ov::Output<const ov::Node>& port, const std::string& name) {
const auto& shape = port.get_partial_shape();
auto element_type = port.get_element_type();
m_user_inputs[name] = { create_host_tensor(shape, element_type), TensorOwner::PLUGIN };
ov::ISyncInferRequest::set_tensor(port, m_user_inputs.at(name).ptr);
}
void SyncInferRequest::allocate_output(const ov::Output<const ov::Node>& port, const std::string& name) {
const auto& shape = port.get_partial_shape();
auto element_type = port.get_element_type();
m_user_outputs[name] = { create_host_tensor(shape, element_type), TensorOwner::PLUGIN };
ov::ISyncInferRequest::set_tensor(port, m_user_outputs.at(name).ptr);
}
void SyncInferRequest::allocate_inputs() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::allocate_inputs");
for (const auto& it : m_input_ports_map) {
const auto& name = it.first;
const auto& port = it.second;
GPU_DEBUG_LOG << "[init " << name << " input blob]" << std::endl;
bool is_nv12_input = false;
if (port.get_rt_info().count(ov::preprocess::TensorInfoMemoryType::get_type_info_static())) {
std::string mem_type = port.get_rt_info().at(ov::preprocess::TensorInfoMemoryType::get_type_info_static())
.as<ov::preprocess::TensorInfoMemoryType>().value;
if (mem_type.find(ov::intel_gpu::memory_type::surface) != std::string::npos) {
is_nv12_input = true;
}
}
if (!is_nv12_input) {
allocate_input(port, name);
}
}
}
void SyncInferRequest::allocate_outputs() {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::allocate_outputs");
// allocate outputs
for (const auto& it : m_output_ports_map) {
const auto& name = it.first;
const auto& port = it.second;
GPU_DEBUG_LOG << "[init " << name << " output blob]" << std::endl;
allocate_output(port, name);
}
}
void SyncInferRequest::allocate_states() {
m_graph->get_network()->allocate_variables_memories();
}
std::vector<cldnn::event::ptr> SyncInferRequest::prepare_batched_input(const std::string& name,
const ov::Output<const ov::Node>& port,
const std::vector<ov::SoPtr<ov::ITensor>>& user_tensors) {
std::vector<cldnn::event::ptr> ret_events;
bool is_host = all_host_tensors(user_tensors);
bool is_remote_buffer = all_remote_buffers(user_tensors);
// Host buffers are merged to single tensor
if (is_host || is_remote_buffer) {
auto tmp_shape = user_tensors.at(0)->get_shape();
auto tmp_et = user_tensors.at(0)->get_element_type();
tmp_shape[0] = user_tensors.size();
std::shared_ptr<ov::ITensor> merged_tensor = nullptr;
if (is_host) {
merged_tensor = m_context->create_host_tensor(tmp_et, tmp_shape)._ptr;
auto ptr = static_cast<uint8_t*>(merged_tensor->data());
ov::parallel_for(user_tensors.size(), [&](size_t i) {
const auto& tensor = user_tensors.at(i);
std::memcpy(ptr + i * tensor->get_byte_size(), static_cast<uint8_t*>(tensor->data()), tensor->get_byte_size());
});
} else {
const auto& stream = m_graph->get_network()->get_stream();
merged_tensor = m_context->create_tensor(tmp_et, tmp_shape, {})._ptr;
auto merged_memory = std::dynamic_pointer_cast<RemoteTensorImpl>(merged_tensor)->get_memory();
cldnn::mem_lock<uint8_t> dst_lock(merged_memory, stream);
for (size_t i = 0; i < user_tensors.size(); i++) {
auto input_tensor = std::dynamic_pointer_cast<RemoteTensorImpl>(user_tensors[i]._ptr);
cldnn::mem_lock<uint8_t> src_lock(input_tensor->get_memory(), stream);
std::memcpy(dst_lock.data() + i * input_tensor->get_byte_size(), src_lock.data(), input_tensor->get_byte_size());
}
}
auto events = prepare_input(name, port, {merged_tensor, TensorOwner::PLUGIN});
std::move(events.begin(), events.end(), std::back_inserter(ret_events));
} else {
for (size_t i = 0; i < user_tensors.size(); i++) {
auto new_name = name + "_" + std::to_string(i);
auto events = prepare_input(new_name, port, {user_tensors[i]._ptr, TensorOwner::USER});
std::move(events.begin(), events.end(), std::back_inserter(ret_events));
}
}
return ret_events;
}
std::vector<cldnn::event::ptr> SyncInferRequest::prepare_input(const std::string& name,
const ov::Output<const ov::Node>& port,
const TensorWrapper& user_tensor_wrapper) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::prepare_input");
auto pshape = port.get_partial_shape();
auto is_dynamic = pshape.is_dynamic();
auto user_tensor = user_tensor_wrapper.ptr;
auto element_type = user_tensor->get_element_type();
auto remote_ptr = std::dynamic_pointer_cast<RemoteTensorImpl>(user_tensor);
bool is_remote = remote_ptr != nullptr;
auto network = m_graph->get_network();
auto& engine = m_graph->get_engine();
auto& stream = network->get_stream();
OPENVINO_ASSERT(pshape.compatible(ov::PartialShape(user_tensor->get_shape())) || is_batched_input(port),
"[GPU] The input tensor size is not equal to model port shape, can't handle input tensor with name: ",
name,
", because model input (shape=",
pshape,
") and tensor (shape=",
user_tensor->get_shape(),
") are incompatible");
if (is_remote) {
m_plugin_inputs[name] = user_tensor_wrapper;
}
auto device_tensor_et = convert_to_supported_device_type(element_type);
bool convert_needed = is_convert_required(element_type, device_tensor_et);
bool update_device_tensor = m_plugin_inputs.count(name) == 0 || (m_plugin_inputs[name].owner == TensorOwner::USER && !is_remote);
if (update_device_tensor) {
// If device input hasn't been created, then try to use user memory if it's usm_host, or allocate new device buffer
m_plugin_inputs[name] = create_or_share_device_tensor(user_tensor_wrapper, name, pshape, device_tensor_et, convert_needed);
} else if (!is_remote) {
// Device memory has been created on previous iterations. Try to reuse whenever it's possible
auto device_tensor_wrapper = m_plugin_inputs.at(name);
auto device_tensor = std::dynamic_pointer_cast<RemoteTensorImpl>(device_tensor_wrapper.ptr);
if (is_dynamic) {
if (device_tensor->get_original_memory()->size() < user_tensor->get_byte_size()) {
auto& shape_predictor = network->get_shape_predictor();
auto actual_shape = predict_shape(name, user_tensor->get_shape(), device_tensor_et, shape_predictor);
auto new_tensor = create_device_tensor(actual_shape, device_tensor_et, false);
new_tensor->set_shape(user_tensor->get_shape());
m_plugin_inputs[name] = { new_tensor, TensorOwner::PLUGIN };
}
}
}
auto device_tensor = std::dynamic_pointer_cast<RemoteTensorImpl>(m_plugin_inputs.at(name).ptr);
if (is_dynamic) {
OPENVINO_ASSERT(device_tensor->get_original_memory()->size() >= user_tensor->get_size(),
"[GPU] Size of input device tensor (=",
device_tensor->get_original_memory()->size(),
") is expected to be greater or equal to user tensor (=",
user_tensor->get_size(),
") in dynamic case for ", name);
// tensor reshape below is expected to work w/o reallocation
device_tensor->set_shape(user_tensor->get_shape());
} else {
OPENVINO_ASSERT(device_tensor->get_size() == user_tensor->get_size(),
"[GPU] Size of user tensor (=",
user_tensor->get_size(),
") and device tensor (=",
device_tensor->get_size(),
") don't match for ", name,
". Those are expected to be equal in case of static shape of the port");
}
auto memory = device_tensor->get_memory();
// WA to extend shape to ranks expected by legacy shape infer. Remove after full migration to new shape infer
if (!m_graph->get_config().get_property(ov::intel_gpu::allow_new_shape_infer)) {
auto new_layout = memory->get_layout();
new_layout.set_partial_shape(m_graph->get_input_layouts().at(name).get_shape());
memory = engine.reinterpret_buffer(*memory, new_layout);
}
cldnn::event::ptr ret_event = nullptr;
if (!is_remote) {
if (device_tensor->get_element_type() != user_tensor->get_element_type()) {
convert_and_copy(user_tensor.get(), device_tensor.get(), stream);
} else {
auto src_ptr = static_cast<uint8_t*>(user_tensor->data());
if (!same_host_mem(memory, src_ptr)) {
ret_event = memory->copy_from(stream, src_ptr, false);
}
}
}
const cldnn::primitive_id internal_name = "parameter:" + name;
network->set_input_data(internal_name, memory);
if (ret_event)
return { ret_event };
else
return {};
}
std::vector<cldnn::event::ptr> SyncInferRequest::prepare_output(const std::string& name,
const ov::Output<const ov::Node>& port,
const TensorWrapper& user_tensor_wrapper) {
OV_ITT_SCOPED_TASK(itt::domains::intel_gpu_plugin, "SyncInferRequest::prepare_output");
auto pshape = port.get_partial_shape();
auto is_dynamic = pshape.is_dynamic();
auto element_type = port.get_element_type();
auto user_tensor = user_tensor_wrapper.ptr;
auto remote_ptr = std::dynamic_pointer_cast<RemoteTensorImpl>(user_tensor);
bool is_remote = remote_ptr != nullptr;
if (user_tensor->get_size() > 0) {
OPENVINO_ASSERT(pshape.compatible(ov::PartialShape(user_tensor->get_shape())),
"[GPU] The output tensor size is not equal to model port shape, can't handle output tensor with name: ",
name,
", because model output (shape=",
pshape,
") and tensor (shape=",
user_tensor->get_shape(),
") are incompatible");
}
auto network = m_graph->get_network();
auto device_tensor_et = convert_to_supported_device_type(element_type);
bool convert_needed = is_convert_required(device_tensor_et, element_type);
cldnn::primitive_id internal_name = m_output_names_map.at(name);
if (is_remote && !convert_needed) {
m_plugin_outputs[name] = user_tensor_wrapper;
}
if (!is_dynamic) {
auto is_cpu_impl = network->is_cpu_impl(internal_name);
bool has_device_buffer = m_plugin_outputs.count(name) > 0;
bool update_device_tensor = !has_device_buffer ||
(m_plugin_outputs[name].owner == TensorOwner::USER && !is_remote);
if (update_device_tensor) {
m_plugin_outputs[name] = create_or_share_device_tensor(user_tensor_wrapper, name, pshape, device_tensor_et, is_cpu_impl || convert_needed);
}
}
// Missing output in _plugin_outputs means that the network is dynamic and outputs couldn't be pre-allocated
if (m_plugin_outputs.find(name) == m_plugin_outputs.end())
return {};
auto output_tensor = std::dynamic_pointer_cast<RemoteTensorImpl>(m_plugin_outputs.at(name).ptr);
auto output_memory = output_tensor->get_memory();
return network->set_output_memory(internal_name, output_memory);
}
void SyncInferRequest::init_mappings(bool is_legacy_api) {
for (const auto& in : get_inputs()) {
auto port_name = get_port_name(in, is_legacy_api);
m_input_ports_map[port_name] = in;
}
for (const auto& out : get_outputs()) {
auto port_name = get_port_name(out, is_legacy_api);
m_output_ports_map[port_name] = out;
m_output_names_map[port_name] = m_graph->out_name_to_internal(port_name);
}
}
bool SyncInferRequest::is_batched_input(const ov::Output<const ov::Node>& port) const {
return m_batched_tensors.count(port.get_tensor_ptr()) > 0;
}
} // namespace intel_gpu
} // namespace ov
@@ -36,7 +36,7 @@ std::vector<std::pair<size_t, size_t>> compute_einsum_path(std::shared_ptr<const
// TODO: implement algorithm for finding (pseudo-)optimal einsum_path
std::vector<std::pair<size_t, size_t>> einsum_path;
const size_t num_inputs = einsum_node->get_input_size();
NGRAPH_CHECK(num_inputs > 0);
OPENVINO_ASSERT(num_inputs > 0);
for (size_t input_ind = num_inputs - 1; input_ind > 0; --input_ind) {
einsum_path.push_back(std::make_pair(0, input_ind));
}
@@ -141,9 +141,9 @@ std::string generate_grouping_subscript(const std::string& input_subscript, cons
///
void update_operands(ov::OutputVector& input_nodes, std::vector<std::string>& input_subscripts, size_t input_ind1, size_t input_ind2,
const ov::Output<ov::Node>& new_node, const std::string& new_subscript) {
NGRAPH_CHECK(input_ind1 < input_ind2);
NGRAPH_CHECK(input_ind2 < input_nodes.size());
NGRAPH_CHECK(input_ind2 < input_subscripts.size());
OPENVINO_ASSERT(input_ind1 < input_ind2);
OPENVINO_ASSERT(input_ind2 < input_nodes.size());
OPENVINO_ASSERT(input_ind2 < input_subscripts.size());
input_nodes.erase(input_nodes.begin() + input_ind2);
input_nodes.erase(input_nodes.begin() + input_ind1);
input_nodes.push_back(new_node);
@@ -163,7 +163,7 @@ void update_operands(ov::OutputVector& input_nodes, std::vector<std::string>& in
/// \return sub-shape
///
ov::Shape compute_sub_shape(const ov::Shape& input_shape, size_t begin, size_t end, bool is_product = false) {
NGRAPH_CHECK(end <= input_shape.size());
OPENVINO_ASSERT(end <= input_shape.size());
if (end <= begin) {
return ov::Shape();
}
@@ -260,12 +260,12 @@ LabelDimMap compute_label_dim_map(const ov::Rank& input_rank,
static const std::string ellipsis = "...";
const auto labels = ov::op::v7::Einsum::extract_labels(input_subscript);
const auto static_input_rank = input_rank.is_static();
NGRAPH_CHECK(static_input_rank || (std::find(labels.begin(), labels.end(), ellipsis) == labels.end()),
OPENVINO_ASSERT(static_input_rank || (std::find(labels.begin(), labels.end(), ellipsis) == labels.end()),
"Input rank cannot be dynamic in case of ellipsis in input subscript");
const size_t input_rank_length = static_input_rank ? input_rank.get_length() : labels.size();
NGRAPH_CHECK(input_rank_length >= labels.size());
OPENVINO_ASSERT(input_rank_length >= labels.size());
const size_t num_broadcasted_dims = input_rank_length - labels.size() + 1;
NGRAPH_CHECK(num_broadcasted_dims > 0);
OPENVINO_ASSERT(num_broadcasted_dims > 0);
LabelDimMap resulted_map;
size_t current_dim = 0;
@@ -304,8 +304,8 @@ void transpose_input(ov::OutputVector& input_nodes, std::vector<std::string>& in
ov::NodeVector& subgraph_nodes) {
// perform sanity check for arguments
const auto num_inputs = input_nodes.size();
NGRAPH_CHECK(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
NGRAPH_CHECK(input_ind < num_inputs, "Input index is out of range.");
OPENVINO_ASSERT(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
OPENVINO_ASSERT(input_ind < num_inputs, "Input index is out of range.");
// generate permutation vector by searching for bijection between input_subscripts
// and required_subscript
@@ -322,11 +322,11 @@ void transpose_input(ov::OutputVector& input_nodes, std::vector<std::string>& in
const auto& input_node = input_nodes[input_ind];
const auto labels = ov::op::v7::Einsum::extract_labels(input_subscript);
const auto required_labels = ov::op::v7::Einsum::extract_labels(required_subscript);
NGRAPH_CHECK(labels.size() == required_labels.size());
OPENVINO_ASSERT(labels.size() == required_labels.size());
const auto label_dim_map = compute_label_dim_map(input_node.get_partial_shape().rank(), input_subscript);
for (const auto& required_label : required_labels) {
const auto label_dims_it = label_dim_map.find(required_label);
NGRAPH_CHECK(label_dims_it != label_dim_map.end());
OPENVINO_ASSERT(label_dims_it != label_dim_map.end());
const auto& label_dims = label_dims_it->second;
permutation.insert(permutation.end(), label_dims.begin(), label_dims.end());
}
@@ -360,8 +360,8 @@ void reduce_input(EinsumDecomposition *einsum_decompose_ptr,
const std::string& output_subscript, size_t input_ind, ov::NodeVector& subgraph_nodes) {
// perform sanity check for arguments
const auto num_inputs = input_nodes.size();
NGRAPH_CHECK(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
NGRAPH_CHECK(input_ind < num_inputs, "Input index is out of range.");
OPENVINO_ASSERT(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
OPENVINO_ASSERT(input_ind < num_inputs, "Input index is out of range.");
const auto& input_node = input_nodes[input_ind];
const auto& input_subscript = input_subscripts[input_ind];
@@ -377,7 +377,7 @@ void reduce_input(EinsumDecomposition *einsum_decompose_ptr,
// or the output subscript
const bool is_dim_reduced = is_dimension_reduced(input_subscripts, output_subscript, label, {input_ind});
NGRAPH_CHECK(label_dim_map.find(label) != label_dim_map.end());
OPENVINO_ASSERT(label_dim_map.find(label) != label_dim_map.end());
const auto& label_dims = label_dim_map[label];
// if label is not met, dimension corresponding to the label is to reduce
@@ -416,7 +416,7 @@ void broadcast_input(ov::OutputVector& inputs,
const ov::Shape& reduced_shape,
bool is_separate_first,
ov::NodeVector& subgraph_nodes) {
NGRAPH_CHECK(input_ind < inputs.size());
OPENVINO_ASSERT(input_ind < inputs.size());
const auto& input = inputs[input_ind];
ov::Shape new_shape{new_common_shape.begin(), new_common_shape.end()};
@@ -434,7 +434,7 @@ void broadcast_input(ov::OutputVector& inputs,
}
const auto old_shape_size = old_shape.size();
const auto new_shape_size = new_shape.size();
NGRAPH_CHECK(old_shape_size <= new_shape_size);
OPENVINO_ASSERT(old_shape_size <= new_shape_size);
const auto new_shape_const = ov::op::v0::Constant::create(ov::element::Type_t::i64, ov::Shape {new_shape.size()}, new_shape);
const auto broadcast = std::make_shared<ov::op::v3::Broadcast>(input, new_shape_const, ov::op::BroadcastType::NUMPY);
@@ -447,13 +447,13 @@ void broadcast_input(ov::OutputVector& inputs,
ov::Output<ov::Node> build_identity(const ov::Output<ov::Node>& input_node,
const std::vector<size_t>& repeated_label_dims,
ov::NodeVector& subgraph_nodes) {
NGRAPH_CHECK(repeated_label_dims.size() > 1);
OPENVINO_ASSERT(repeated_label_dims.size() > 1);
const auto input_shape = input_node.get_shape();
ov::Shape identity_shape(input_shape.size(), 1);
const size_t repeated_label_dim_size = input_shape[repeated_label_dims[0]];
for (const auto dim : repeated_label_dims) {
NGRAPH_CHECK(dim < input_shape.size());
NGRAPH_CHECK(repeated_label_dim_size == input_shape[dim]);
OPENVINO_ASSERT(dim < input_shape.size());
OPENVINO_ASSERT(repeated_label_dim_size == input_shape[dim]);
identity_shape[dim] = repeated_label_dim_size;
}
@@ -481,11 +481,11 @@ ov::Output<ov::Node> build_multi_identity(EinsumDecomposition* einsum_decompose_
const std::vector<std::string>& repeated_labels,
const LabelDimMap& label_dim_map,
ov::NodeVector& subgraph_nodes) {
NGRAPH_CHECK(repeated_labels.size() > 0);
OPENVINO_ASSERT(repeated_labels.size() > 0);
const auto get_identity = [&](size_t idx) {
const auto repeated_label_dims = label_dim_map.find(repeated_labels[idx]);
NGRAPH_CHECK(repeated_label_dims != label_dim_map.end());
OPENVINO_ASSERT(repeated_label_dims != label_dim_map.end());
return build_identity(input_node, repeated_label_dims->second, subgraph_nodes);
};
@@ -522,11 +522,11 @@ void prepare_diagonal_extraction_data(
}
const auto dims_it = label_dim_map.find(label);
NGRAPH_CHECK(dims_it != label_dim_map.end());
OPENVINO_ASSERT(dims_it != label_dim_map.end());
auto dims = dims_it->second;
const auto dims_size = dims.size();
NGRAPH_CHECK(dims_size > 0);
OPENVINO_ASSERT(dims_size > 0);
if (label != ellipsis && dims_size > 1) {
// repeated label is found
@@ -539,7 +539,7 @@ void prepare_diagonal_extraction_data(
}
resultant_subscript += label;
for (const auto dim : dims) {
NGRAPH_CHECK(dim < input_shape.size());
OPENVINO_ASSERT(dim < input_shape.size());
result_shape.push_back(input_shape[dim]);
}
}
@@ -552,8 +552,8 @@ void extract_diagonal(EinsumDecomposition* einsum_decompose_ptr,
ov::NodeVector& subgraph_nodes) {
// perform sanity check for arguments
const auto num_inputs = inputs.size();
NGRAPH_CHECK(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
NGRAPH_CHECK(input_ind < num_inputs, "Input index is out of range.");
OPENVINO_ASSERT(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
OPENVINO_ASSERT(input_ind < num_inputs, "Input index is out of range.");
const auto& input_node = inputs[input_ind];
const auto& input_subscript = input_subscripts[input_ind];
@@ -604,19 +604,19 @@ void compute_ranges(const ov::Rank& input_rank,
size_t common_rank = common_labels.size();
if (std::find(common_labels.begin(), common_labels.end(), ellipsis) != common_labels.end()) {
NGRAPH_CHECK(label_to_dim_map.find(ellipsis) != label_to_dim_map.end());
OPENVINO_ASSERT(label_to_dim_map.find(ellipsis) != label_to_dim_map.end());
common_rank += label_to_dim_map[ellipsis].size() - 1;
}
size_t sep_rank = sep_labels.size();
if (std::find(sep_labels.begin(), sep_labels.end(), ellipsis) != sep_labels.end()) {
NGRAPH_CHECK(label_to_dim_map.find(ellipsis) != label_to_dim_map.end());
OPENVINO_ASSERT(label_to_dim_map.find(ellipsis) != label_to_dim_map.end());
sep_rank += label_to_dim_map[ellipsis].size() - 1;
}
size_t reduced_rank = reduced_labels.size();
if (std::find(reduced_labels.begin(), reduced_labels.end(), ellipsis) != reduced_labels.end()) {
NGRAPH_CHECK(label_to_dim_map.find(ellipsis) != label_to_dim_map.end());
OPENVINO_ASSERT(label_to_dim_map.find(ellipsis) != label_to_dim_map.end());
reduced_rank += label_to_dim_map[ellipsis].size() - 1;
}
@@ -660,8 +660,8 @@ void contract_two_inputs(EinsumDecomposition* einsum_decompose_ptr,
// perform sanity check for arguments
auto num_inputs = input_nodes.size();
NGRAPH_CHECK(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
NGRAPH_CHECK(input_ind2 < num_inputs && input_ind1 != input_ind2, "Incorrect input index is specified.");
OPENVINO_ASSERT(num_inputs == input_subscripts.size(), "Each input must have own subscript.");
OPENVINO_ASSERT(input_ind2 < num_inputs && input_ind1 != input_ind2, "Incorrect input index is specified.");
const auto& input_node1 = input_nodes[input_ind1];
const auto& input_node2 = input_nodes[input_ind2];
@@ -746,7 +746,7 @@ void contract_two_inputs(EinsumDecomposition* einsum_decompose_ptr,
std::vector<int64_t> unsqueeze_axis1;
std::vector<int64_t> unsqueeze_axis2;
for (const auto& sep_label2 : separate_labels2) {
NGRAPH_CHECK(label_to_dim_map2.find(sep_label2) != label_to_dim_map2.end());
OPENVINO_ASSERT(label_to_dim_map2.find(sep_label2) != label_to_dim_map2.end());
const auto label_dims = label_to_dim_map2[sep_label2];
for (size_t dim_ind = 0; dim_ind < label_dims.size(); ++dim_ind) {
unsqueeze_axis1.push_back(unsqueeze_dim + static_cast<int64_t>(dim_ind));
@@ -754,7 +754,7 @@ void contract_two_inputs(EinsumDecomposition* einsum_decompose_ptr,
++unsqueeze_dim;
}
for (const auto& sep_label1 : separate_labels1) {
NGRAPH_CHECK(label_to_dim_map1.find(sep_label1) != label_to_dim_map1.end());
OPENVINO_ASSERT(label_to_dim_map1.find(sep_label1) != label_to_dim_map1.end());
const auto label_dims = label_to_dim_map1[sep_label1];
for (const auto label_dim : label_dims) {
unsqueeze_axis2.push_back(label_dim);
@@ -928,7 +928,7 @@ EinsumDecomposition::EinsumDecomposition() {
extract_diagonal(this, input_nodes, input_subscripts, 0, subgraph_nodes);
// reduce dimensions for the remained input node
NGRAPH_CHECK(input_nodes.size() == 1);
OPENVINO_ASSERT(input_nodes.size() == 1);
reduce_input(this, input_nodes, input_subscripts, output_subscript, 0, subgraph_nodes);
// transpose dimensions to layout required by the output subscript
@@ -229,9 +229,11 @@ void TransformationsPipeline::apply(std::shared_ptr<ov::Model> func) {
pass_config->set_callback<ov::pass::KeepConstAndDecompression>(is_matmul_output);
const bool keep_precision_sensitive_in_fp32_1 = true;
const bool convert_input_output_precision = false;
manager.register_pass<ov::pass::ConvertPrecision>(fp_convert_precision_map,
empty_fuse_map,
keep_precision_sensitive_in_fp32_1);
keep_precision_sensitive_in_fp32_1,
convert_input_output_precision);
manager.register_pass<ov::pass::CommonOptimizations>();
@@ -283,7 +285,11 @@ void TransformationsPipeline::apply(std::shared_ptr<ov::Model> func) {
};
manager.register_pass<ov::pass::Validate>();
manager.register_pass<ov::pass::ConvertPrecision>(int_convert_precision_map);
const bool keep_precision_sensitive_in_fp32_2 = true;
manager.register_pass<ov::pass::ConvertPrecision>(int_convert_precision_map,
empty_fuse_map,
keep_precision_sensitive_in_fp32_2,
convert_input_output_precision);
pass_config->disable<ov::pass::EyeDecomposition>();
@@ -1,69 +1,52 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <intel_gpu/plugin/variable_state.hpp>
#include <blob_factory.hpp>
#include "openvino/runtime/make_tensor.hpp"
#include "intel_gpu/plugin/remote_tensor.hpp"
#include "intel_gpu/plugin/variable_state.hpp"
#include "intel_gpu/runtime/layout.hpp"
#include <memory>
namespace ov {
namespace intel_gpu {
VariableState::VariableState(const std::string &name,
const std::vector<cldnn::network::VariableState::Ptr> &states,
cldnn::engine& engine, int currentBatch)
: InferenceEngine::IVariableStateInternal {name}
, currentBatch_ {currentBatch}
, states_ {states}
, desc_ {
PrecisionFromDataType(states.front()->memory->get_layout().data_type),
AggregateShape(states.front()->memory->get_layout()),
InferenceEngine::Layout::ANY
VariableState::VariableState(const std::string &name, cldnn::network::VariableState::Ptr state, cldnn::engine& engine)
: ov::IVariableState {name}
, m_variable_state(state)
, m_engine(engine) {
auto internal_memory = m_variable_state->memory;
auto internal_layout = internal_memory->get_layout();
auto et = cldnn::data_type_to_element_type(internal_layout.data_type);
auto shape = internal_layout.get_shape();
m_state = ov::make_tensor(et, shape);
}
void VariableState::reset() {
m_variable_state->is_set = false;
}
void VariableState::set_state(const ov::SoPtr<ov::ITensor>& state) {
const bool blocking = true;
auto remote_ptr = std::dynamic_pointer_cast<RemoteTensorImpl>(state._ptr);
if (remote_ptr != nullptr) {
auto user_memory = remote_ptr->get_memory();
cldnn::mem_lock<uint8_t> lock(user_memory, m_engine.get_service_stream());
m_variable_state->memory->copy_from(m_engine.get_service_stream(), lock.data(), blocking);
} else {
auto data = state->data();
m_variable_state->memory->copy_from(m_engine.get_service_stream(), data, blocking);
}
, engine_(engine) { }
void VariableState::Reset() {
IterateOverStates([](cldnn::network::VariableState &state) {
state.is_set = false;
});
m_variable_state->is_set = true;
}
void VariableState::SetState(const InferenceEngine::Blob::Ptr &newState) {
auto lock = std::dynamic_pointer_cast<InferenceEngine::MemoryBlob>(newState)->rmap();
auto data = lock.as<char*>();
IterateOverStates([&data, this](cldnn::network::VariableState &state) {
state.memory->copy_from(engine_.get_service_stream(), data);
data += state.memory->get_layout().bytes_count();
state.is_set = true;
});
engine_.get_service_stream().enqueue_barrier();
}
const ov::SoPtr<ov::ITensor>& VariableState::get_state() const {
auto internal_memory = m_variable_state->memory;
const bool blocking = true;
internal_memory->copy_to(m_engine.get_service_stream(), m_state->data(), blocking);
InferenceEngine::Blob::CPtr VariableState::GetState() const {
auto blob = make_blob_with_precision(desc_, InferenceEngine::CreateDefaultAllocator());
blob->allocate();
auto blobLock = std::dynamic_pointer_cast<InferenceEngine::MemoryBlob>(blob)->wmap();
auto data = blobLock.as<char*>();
IterateOverStates([&data, this](cldnn::network::VariableState &state) {
cldnn::mem_lock<char, cldnn::mem_lock_type::read> lock { state.memory, engine_.get_service_stream() };
std::copy(lock.begin(), lock.end(), data);
data += state.memory->get_layout().bytes_count();
});
return blob;
}
InferenceEngine::SizeVector VariableState::AggregateShape(const cldnn::layout &layout) {
const auto& dims = layout.get_dims();
InferenceEngine::SizeVector shape {dims.begin(), dims.end()};
if (currentBatch_ != -1)
shape.front() = currentBatch_;
return shape;
}
void VariableState::IterateOverStates(std::function<void(cldnn::network::VariableState&)> f) const {
for (size_t i = 0; i < states_.size(); i++) {
auto batch = 1 << i;
if (batch & currentBatch_)
f(*states_[i]);
}
return m_state;
}
} // namespace intel_gpu
@@ -0,0 +1,18 @@
// Copyright (C) 2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "intel_gpu/runtime/file_util.hpp"
#include <stdexcept>
namespace ov {
namespace intel_gpu {
void save_binary(const std::string &path, std::vector<uint8_t> binary) {
try {
ov::util::save_binary(path, binary);
} catch (std::runtime_error&) {}
}
} // namespace intel_gpu
} // namespace ov
@@ -13,7 +13,7 @@
#include "intel_gpu/graph/serialization/string_serializer.hpp"
#include "intel_gpu/runtime/debug_configuration.hpp"
#include "intel_gpu/runtime/itt.hpp"
#include "openvino/util/file_util.hpp"
#include "intel_gpu/runtime/file_util.hpp"
#ifdef WIN32
#include <sdkddkver.h>
@@ -272,7 +272,7 @@ void kernels_cache::build_batch(const engine& build_engine, const batch_program&
// Bucket size can be changed in get_max_kernels_per_batch() method, but forcing it to 1 will lead to much longer
// compile time.
std::lock_guard<std::mutex> lock(cacheAccessMutex);
ov::util::save_binary(cached_bin_name, getProgramBinaries(program));
ov::intel_gpu::save_binary(cached_bin_name, getProgramBinaries(program));
}
} else {
cl::Program program(cl_build_engine.get_cl_context(), {cl_build_engine.get_cl_device()}, precompiled_kernels);
@@ -32,7 +32,7 @@ cl::PFN_clCreateFromD3D11Buffer cl::BufferDX::pfn_clCreateFromD3D11Buffer = NULL
#ifdef ENABLE_ONEDNN_FOR_GPU
#include <oneapi/dnnl/dnnl_ocl.hpp>
#include "openvino/util/file_util.hpp"
#include "intel_gpu/runtime/file_util.hpp"
#endif
namespace cldnn {
@@ -89,7 +89,7 @@ void ocl_engine::create_onednn_engine(const ExecutionConfig& config) {
_onednn_engine = std::make_shared<dnnl::engine>(dnnl::ocl_interop::make_engine(casted->get_device().get(), casted->get_context().get()));
onednn_cache_blob = dnnl::ocl_interop::get_engine_cache_blob(*_onednn_engine);
ov::util::save_binary(path, onednn_cache_blob);
ov::intel_gpu::save_binary(path, onednn_cache_blob);
} else {
_onednn_engine = std::make_shared<dnnl::engine>(dnnl::ocl_interop::make_engine(casted->get_device().get(), casted->get_context().get(),
onednn_cache_blob));
@@ -176,15 +176,19 @@ gpu_image2d::gpu_image2d(ocl_engine* engine, const layout& layout)
type = CL_UNORM_INT8;
break;
case format::nv12:
_width = layout.spatial(1);
_height = layout.spatial(0);
if (layout.feature() == 2) {
{
// [NHWC] dimensions order
auto shape = layout.get_shape();
_width = shape[2];
_height = shape[1];
if (shape[3] == 2) {
order = CL_RG;
} else if (layout.feature() > 2) {
} else if (shape[3] > 2) {
CLDNN_ERROR_MESSAGE("2D image allocation", "invalid number of channels in NV12 input image!");
}
type = CL_UNORM_INT8;
break;
}
default:
CLDNN_ERROR_MESSAGE("2D image allocation", "unsupported image type!");
}
@@ -8,6 +8,7 @@
#include "shared_test_classes/base/ov_subgraph.hpp"
#include <cpp/ie_cnn_network.h>
#include <ie_plugin_config.hpp>
#include "functional_test_utils/skip_tests_config.hpp"
#include "functional_test_utils/ov_plugin_cache.hpp"
#include "common_test_utils/common_utils.hpp"
@@ -96,6 +97,7 @@ protected:
};
TEST_P(MemoryDynamicBatch, MultipleInferencesOnTheSameInferRequest) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
auto compiledModel = core_->compile_model(model_, ov::test::utils::DEVICE_GPU, { });
auto inferRequest = compiledModel.create_infer_request();
input_ = generateInput(inputShape_);
@@ -112,6 +114,7 @@ TEST_P(MemoryDynamicBatch, MultipleInferencesOnTheSameInferRequest) {
}
TEST_P(MemoryDynamicBatch, ResetVariableState) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
auto compiledModel = core_->compile_model(model_, ov::test::utils::DEVICE_GPU, { });
auto inferRequest = compiledModel.create_infer_request();
input_ = generateInput(inputShape_);
@@ -129,6 +132,7 @@ TEST_P(MemoryDynamicBatch, ResetVariableState) {
}
TEST_P(MemoryDynamicBatch, GetVariableState) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
auto compiledModel = core_->compile_model(model_, ov::test::utils::DEVICE_GPU, { });
auto inferRequest = compiledModel.create_infer_request();
input_ = generateInput(inputShape_);
@@ -145,6 +149,7 @@ TEST_P(MemoryDynamicBatch, GetVariableState) {
}
TEST_P(MemoryDynamicBatch, SetVariableState) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
auto compiledModel = core_->compile_model(model_, ov::test::utils::DEVICE_GPU, { });
auto inferRequest = compiledModel.create_infer_request();
input_ = generateInput(inputShape_);
@@ -7,11 +7,12 @@
#include <vector>
#include <memory>
#include "common_test_utils/test_assertions.hpp"
#include "openvino/core/except.hpp"
#include "openvino/runtime/intel_gpu/ocl/ocl.hpp"
#include "openvino/runtime/core.hpp"
#include "openvino/runtime/intel_gpu/properties.hpp"
#include <gpu/gpu_config.hpp>
#include <remote_blob_tests/remote_blob_helpers.hpp>
#include <common_test_utils/test_common.hpp>
#include <functional_test_utils/plugin_cache.hpp>
@@ -877,8 +878,8 @@ TEST_F(OVRemoteTensor_Test, NV12toGray) {
// ------------------------------------------------------
// Prepare input data
ov::Tensor fake_image = ov::test::utils::create_and_fill_tensor(ov::element::i8, {1, feature, height, width}, 50, 0, 1);
ov::Tensor fake_image_regular = ov::test::utils::create_and_fill_tensor(ov::element::f32, {1, feature, height, width});
ov::Tensor fake_image = ov::test::utils::create_and_fill_tensor(ov::element::i8, {1, height, width, feature}, 50, 0, 1);
ov::Tensor fake_image_regular = ov::test::utils::create_and_fill_tensor(ov::element::f32, {1, height, width, feature });
auto image_ptr = static_cast<uint8_t*>(fake_image.data());
auto image_ptr_regular = static_cast<float*>(fake_image_regular.data());
@@ -943,12 +944,13 @@ TEST_F(OVRemoteTensor_Test, NV12toGray) {
// ------------------------------------------------------
// regular inference
auto fn_ptr_regular = ngraph::builder::subgraph::makeConvPoolRelu({1, 1, height, width});
auto fn_ptr_regular = ngraph::builder::subgraph::makeConvPoolRelu({1, feature, height, width});
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::f32)
.set_layout("NHWC")
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().model().set_layout("NHWC");
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
auto param_input_y_regular = function_regular->get_parameters().at(0);
@@ -978,8 +980,8 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_ConvertTranspose) {
// ------------------------------------------------------
// Prepare input data
ov::Tensor fake_image_data_y = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1);
ov::Tensor fake_image_data_uv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1);
ov::Tensor fake_image_data_y = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height, width, 1}, 50, 0, 1);
ov::Tensor fake_image_data_uv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height / 2, width / 2, 2}, 256, 0, 1);
auto ie = ov::Core();
@@ -991,7 +993,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_ConvertTranspose) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(SURFACE));
.set_memory_type(ov::intel_gpu::memory_type::surface);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1056,7 +1058,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_ConvertTranspose) {
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().preprocess().convert_color(ColorFormat::BGR);
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
@@ -1087,7 +1089,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_single_plane) {
// ------------------------------------------------------
// Prepare input data
ov::Tensor fake_image_data_yuv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 1, height * 3 / 2, width}, 50);
ov::Tensor fake_image_data_yuv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height * 3 / 2, width, 1}, 50);
auto ie = ov::Core();
@@ -1099,7 +1101,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_single_plane) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_SINGLE_PLANE)
.set_memory_type(GPU_CONFIG_KEY(SURFACE));
.set_memory_type(ov::intel_gpu::memory_type::surface);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1147,7 +1149,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_single_plane) {
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_SINGLE_PLANE)
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().preprocess().convert_color(ColorFormat::BGR);
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
@@ -1177,8 +1179,8 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_two_planes) {
// ------------------------------------------------------
// Prepare input data
ov::Tensor fake_image_data_y = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1);
ov::Tensor fake_image_data_uv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1);
ov::Tensor fake_image_data_y = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height, width, 1}, 50, 0, 1);
ov::Tensor fake_image_data_uv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height / 2, width / 2, 2}, 256, 0, 1);
auto ie = ov::Core();
@@ -1190,7 +1192,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_two_planes) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(SURFACE));
.set_memory_type(ov::intel_gpu::memory_type::surface);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1255,7 +1257,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_image_two_planes) {
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().preprocess().convert_color(ColorFormat::BGR);
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
@@ -1286,8 +1288,8 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_buffer) {
// ------------------------------------------------------
// Prepare input data
ov::Tensor fake_image_data_y = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1);
ov::Tensor fake_image_data_uv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1);
ov::Tensor fake_image_data_y = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height, width, 1}, 50, 0, 1);
ov::Tensor fake_image_data_uv = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height / 2, width / 2, 2}, 256, 0, 1);
auto ie = ov::Core();
@@ -1297,7 +1299,7 @@ TEST_F(OVRemoteTensor_Test, NV12toBGR_buffer) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1389,7 +1391,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_image_single_plane) {
std::vector<ov::Tensor> fake_image_data_yuv;
for (size_t i = 0; i < num_batch; i++) {
fake_image_data_yuv.push_back(ov::test::utils::create_and_fill_tensor(
ov::element::u8, {1, 1, height * 3 / 2, width}, 50, 0, 1, static_cast<int32_t>(i)));
ov::element::u8, {1, height * 3 / 2, width, 1}, 50, 0, 1, static_cast<int32_t>(i)));
}
auto ie = ov::Core();
@@ -1402,7 +1404,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_image_single_plane) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_SINGLE_PLANE)
.set_memory_type(GPU_CONFIG_KEY(SURFACE));
.set_memory_type(ov::intel_gpu::memory_type::surface);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1460,7 +1462,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_image_single_plane) {
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_SINGLE_PLANE)
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().preprocess().convert_color(ColorFormat::BGR);
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
@@ -1495,9 +1497,9 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_image_two_planes) {
// Prepare input data
std::vector<ov::Tensor> fake_image_data_y, fake_image_data_uv;
for (size_t i = 0; i < num_batch; i++) {
fake_image_data_y.push_back(ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1, static_cast<int32_t>(i)));
fake_image_data_y.push_back(ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height, width, 1}, 50, 0, 1, static_cast<int32_t>(i)));
fake_image_data_uv.push_back(ov::test::utils::create_and_fill_tensor(
ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1, static_cast<int32_t>(i)));
ov::element::u8, {1, height / 2, width / 2, 2}, 256, 0, 1, static_cast<int32_t>(i)));
}
auto ie = ov::Core();
@@ -1510,7 +1512,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_image_two_planes) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(SURFACE));
.set_memory_type(ov::intel_gpu::memory_type::surface);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1584,7 +1586,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_image_two_planes) {
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().preprocess().convert_color(ColorFormat::BGR);
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
@@ -1623,8 +1625,8 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toGray) {
std::vector<ov::Tensor> fake_image;
std::vector<ov::Tensor> fake_image_regular;
for (size_t i = 0; i < num_batch; i++) {
auto tensor_image = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, feature, height, width}, 50, 0, 1, static_cast<int32_t>(i));
auto tensor_regular = ov::test::utils::create_and_fill_tensor(ov::element::f32, {1, feature, height, width});
auto tensor_image = ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height, width, feature}, 50, 0, 1, static_cast<int32_t>(i));
auto tensor_regular = ov::test::utils::create_and_fill_tensor(ov::element::f32, {1, feature, height, width });
auto image_ptr = static_cast<uint8_t*>(tensor_image.data());
auto image_ptr_regular = static_cast<float*>(tensor_regular.data());
// Apply NV12 (Surface) -> Gray conversion for regular blob
@@ -1739,9 +1741,9 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_buffer) {
// Prepare input data
std::vector<ov::Tensor> fake_image_data_y, fake_image_data_uv;
for (size_t i = 0; i < num_batch * 2; ++i) {
fake_image_data_y.push_back(ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, 1, height, width}, 50, 0, 1, static_cast<int32_t>(i)));
fake_image_data_y.push_back(ov::test::utils::create_and_fill_tensor(ov::element::u8, {1, height, width, 1}, 50, 0, 1, static_cast<int32_t>(i)));
fake_image_data_uv.push_back(ov::test::utils::create_and_fill_tensor(
ov::element::u8, {1, 2, height / 2, width / 2}, 256, 0, 1, static_cast<int32_t>(i)));
ov::element::u8, {1, height / 2, width / 2, 2}, 256, 0, 1, static_cast<int32_t>(i)));
}
auto ie = ov::Core();
@@ -1754,7 +1756,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_buffer) {
auto p = PrePostProcessor(fn_ptr_remote);
p.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p.input().preprocess().convert_color(ColorFormat::BGR);
p.input().model().set_layout("NCHW");
auto function = p.build();
@@ -1856,7 +1858,7 @@ TEST_P(OVRemoteTensorBatched_Test, NV12toBGR_buffer) {
auto p_reg = PrePostProcessor(fn_ptr_regular);
p_reg.input().tensor().set_element_type(ov::element::u8)
.set_color_format(ColorFormat::NV12_TWO_PLANES, {"y", "uv"})
.set_memory_type(GPU_CONFIG_KEY(BUFFER));
.set_memory_type(ov::intel_gpu::memory_type::buffer);
p_reg.input().preprocess().convert_color(ColorFormat::BGR);
p_reg.input().model().set_layout("NCHW");
auto function_regular = p_reg.build();
@@ -1931,6 +1933,14 @@ TEST(OVRemoteContextGPU, smoke_CustomContextDeviceNames) {
}
}
TEST(OVRemoteContextGPU, smoke_CantCreateContextForNullHandle) {
#if defined(ANDROID)
GTEST_SKIP();
#endif
auto core = ov::Core();
OV_EXPECT_THROW(ov::intel_gpu::ocl::ClContext(core, nullptr, 0), ov::Exception, HasSubstr("Can't create shared OCL context as user handle is nullptr!"));
}
TEST(OVRemoteContextGPU, smoke_RemoteContextPerDevice) {
#if defined(ANDROID)
GTEST_SKIP();
@@ -9,14 +9,6 @@
std::vector<std::string> disabledTestPatterns() {
return {
// TODO: Issue: 39612
R"(.*Interpolate.*cubic.*tf_half_pixel_for_nn.*FP16.*)",
// TODO: Issue: 43794
R"(.*(PreprocessTest).*(SetScalePreProcessSetBlob).*)",
R"(.*(PreprocessTest).*(SetScalePreProcessGetBlob).*)",
R"(.*(PreprocessTest).*(SetMeanValuePreProcessSetBlob).*)",
R"(.*(PreprocessTest).*(SetMeanImagePreProcessSetBlob).*)",
R"(.*(PreprocessTest).*(ReverseInputChannelsPreProcessGetBlob).*)",
R"(.*(InferRequestPreprocessDynamicallyInSetBlobTest).*)",
// TODO: Issue: 46841
R"(.*(QuantGroupConvBackpropData3D).*)",
@@ -39,8 +31,6 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*ConstantResultSubgraphTest.*inPrc=I16.*)",
// TODO: Issue: 54194
R"(.*ActivationLayerTest.*SoftPlus.*)",
// need to implement Export / Import
R"(.*IEClassImportExportTestP.*)",
R"(.*Behavior.*InferRequestSetBlobByType.*Device=HETERO.*)",
// TODO: Issue: 59586, NormalizeL2 output mismatch for empty axes case
R"(.*NormalizeL2LayerTest.*axes=\(\).*)",
@@ -51,15 +41,11 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*Behavior.*(Multi|Auto).*InferRequestSetBlobByType.*Batched.*)",
R"(.*(Multi|Auto).*Behavior.*InferRequestIOBBlobTest.*canProcessDeallocatedOutputBlobAfterGetAndSetBlob.*)",
// TODO Issue 100145
R"(.*Behavior.*InferRequestIOBBlobTest.*canReallocateExternalBlobViaGet.*)",
R"(.*Behavior.*OVInferRequestIOTensorTest.*canInferAfterIOBlobReallocation.*)",
R"(.*Behavior.*OVInferRequestDynamicTests.*InferUpperBoundNetworkAfterIOTensorsReshaping.*)",
R"(.*(Auto|Multi).*Behavior.*IncorrectConfigTests.*CanNotLoadNetworkWithIncorrectConfig.*)",
// Not implemented yet:
R"(.*Behavior.*ExecutableNetworkBaseTest.*canSetConfigToExecNet.*)",
R"(.*Behavior.*ExecutableNetworkBaseTest.*canExport.*)",
R"(.*OVCompiledModelBaseTest.*CanSetConfigToExecNet.*)",
R"(.*OVCompiledModelBaseTest.*CanSetConfigToExecNetAndCheckConfigAndCheck.*)",
// TODO: Issue 67408
R"(.*smoke_LSTMSequenceCommonClip.*LSTMSequenceTest.*CompareWithRefs.*)",
// TODO: Issue 114262
@@ -68,17 +54,10 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*EltwiseLayerTest.*OpType=Pow.*NetType=i64.*)",
// TODO: Issue: 68712
R"(.*.MatMul.*CompareWithRefs.*IS0=\(1.5\)_IS1=\(1.5\).*transpose_a=0.*transpose_b=1.*CONSTANT.*FP16.*UNSPECIFIED.*UNSPECIFIED.*ANY.*)",
// TODO: Issue 69187
R"(smoke_PrePostProcess.*cvt_color_nv12.*)",
// TODO: Issue 71215
R"(smoke_PrePostProcess.*cvt_color_i420.*)",
// Unsupported
R"(smoke_Behavior/InferRequestSetBlobByType.setInputBlobsByType/BlobType=Batched_Device=GPU_Config=().*)",
// TODO: Issue 72624
R"(smoke_PrePostProcess.*resize_dynamic.*)",
// Issue: CVS-66778
R"(.*smoke_Auto_BehaviorTests.*DynamicOutputToDynamicInput.*)",
R"(.*smoke_Auto_BehaviorTests.*DynamicInputToDynamicOutput.*)",
// Dynamic batch allocates output using upper bound
R"(.*smoke_BehaviorTests.*InferUpperBoundNetworkWithGetTensor.*)",
// need dynamic shapes
@@ -89,16 +68,8 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*smoke.*BehaviorTests.*DynamicInputToDynamicOutput.*)",
// Issue: 76197
R"(.*registerPluginsXMLUnicodePath.*)",
// Not supported yet
R"(.*CompileModelCacheTestBase.*ConvBias.*)",
R"(.*CompileModelCacheTestBase.*KSOFunction.*)",
R"(.*LoadNetworkCacheTestBase.*)",
// Issue: 83014
R"(.*smoke_RemoteBlob.*canInferOnUserQueue.*)",
// Issue: CVS-76980
R"(.*smoke_Auto_BehaviorTests.*InferDynamicNetwork/.*)",
// Issue: CVS-86976
R"(.*smoke_VirtualPlugin_BehaviorTests.*LoadedRemoteContext.*)",
// Issue: CVS-88667 - Need to verify hetero interoperability
R"(.*nightly_OVClassHeteroExecutableNetworlGetMetricTest.*SUPPORTED_(CONFIG_KEYS|METRICS).*)",
// TODO: Issue: 89555
@@ -132,10 +103,10 @@ std::vector<std::string> disabledTestPatterns() {
R"(.*(Auto|Multi).*InferRequestPreprocessTest.*SetPreProcessToInputInfo.*)",
R"(.*(Auto|Multi).*InferRequestPreprocessTest.*SetPreProcessToInferRequest.*)",
// New plugin work with tensors, so it means that blob in old API can have different pointers
R"(.*(Auto|Multi).*InferRequestIOBBlobTest.*secondCallGetInputDoNotReAllocateData.*)",
R"(.*(Auto|Multi).*InferRequestIOBBlobTest.*secondCallGetOutputDoNotReAllocateData.*)",
R"(.*(Auto|Multi).*InferRequestIOBBlobTest.*secondCallGetInputAfterInferSync.*)",
R"(.*(Auto|Multi).*InferRequestIOBBlobTest.*secondCallGetOutputAfterInferSync.*)",
R"(.*InferRequestIOBBlobTest.*secondCallGetInputDoNotReAllocateData.*)",
R"(.*InferRequestIOBBlobTest.*secondCallGetOutputDoNotReAllocateData.*)",
R"(.*InferRequestIOBBlobTest.*secondCallGetInputAfterInferSync.*)",
R"(.*InferRequestIOBBlobTest.*secondCallGetOutputAfterInferSync.*)",
// For some strange reason (bug?) output format cannot have a rank greater than 4 for dynamic shape case,
// because it crashes in some random places during "reorder_inputs" pass.
R"(.*UniqueLayerDynamicGPUTest.*\(\d*\.\d*\.\d*\.\d*\.\d*\).*axis.*)",
@@ -143,5 +114,21 @@ std::vector<std::string> disabledTestPatterns() {
// Plugin version was changed to ov::Version
R"(.*VersionTest.*pluginCurrentVersionIsCorrect.*)",
#endif
// Old API cannot deallocate tensor
R"(.*InferRequestIOBBlobTest.*canProcessDeallocatedOutputBlobAfterGetAndSetBlob.*)",
// Issue: 113704 - Layout information maybe incorrect when covert tensor to blob
R"(.*smoke_.*BehaviorTests/InferRequestPreprocessConversionTest.*NHWC.*)",
// Issue: Disabled due to LPT precision matching issue
R"(.*smoke_.*FakeQuantizeTransformation.*)",
R"(.*smoke_LPT.*ReshapeTransformation.*)",
R"(.*smoke_LPT.*ConvolutionTransformation.*)",
R"(.*smoke_LPT.*MatMulWithConstantTransformation.*)",
R"(.*smoke_LPT.*PullReshapeThroughDequantizationTransformation.*)",
R"(.*smoke_LPT.*ElementwiseBranchSelectionTransformation.*)",
// Dynamic state unsupported for now
R"(.*MemoryDynamicBatch.*)",
// Meta plugins may miss saving HW plugin so handle, thus plugin may be unloaded before all objects are deleted which leads to segfault
// Issue: 118840
R"(.*OVHoldersTest.*)",
};
}
@@ -143,7 +143,7 @@ const std::vector<std::vector<ov::test::InputShape>> dynInputShapes = {
// Input for ShapeOf
{{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{1, 10, 4}, {1, 4, 12}}},
// Input for Add
{{ov::Dimension::dynamic()}, {{1, 10, 4}, {2, 2, 12}}}
{{ov::Dimension::dynamic(), ov::Dimension::dynamic(), ov::Dimension::dynamic()}, {{1, 10, 4}, {2, 2, 12}}}
},
// 4D
{
@@ -313,11 +313,10 @@ TEST_P(can_fuse_reorder, surface_input_reorder) {
std::tie(req_data_type, req_format) = GetParam();
const auto reorder_prim_id = "surface_input_reorder_prim";
auto in_size = tensor{1, 1, 8, 8};
auto weights_size = tensor{32, 1, 8, 8};
auto in_layout = layout(data_types::u8, format::nv12, in_size);
auto in_layout = layout({1, 8, 8, 1}, data_types::u8, format::nv12);
// Set data type the same as input's data type
auto reorder_layout = layout(data_types::u8, format::bfyx, in_size);
auto reorder_layout = layout({1, 8, 8, 1}, data_types::u8, format::bfyx);
auto input_data = engine.allocate_memory({ in_layout });
auto weights_dt = req_data_type == data_types::u8 ? data_types::i8 : req_data_type;
@@ -328,9 +327,10 @@ TEST_P(can_fuse_reorder, surface_input_reorder) {
auto surface_input_reorder_prim = reorder(reorder_prim_id, input_info("input"), reorder_layout);
surface_input_reorder_prim.input_mem_type = reorder::memory_type::surface;
auto conv_input_reorder_prim = reorder("reorder_conv", input_info(reorder_prim_id), req_format, req_data_type);
auto conv_prim = cldnn::convolution("conv", input_info("reorder_conv"), "weights", "", 1, {1, 1}, {1, 1}, {0, 0}, {0, 0}, false);
auto transpose = permute("permute", input_info("reorder_conv"), {0, 3, 1, 2});
auto conv_prim = cldnn::convolution("conv", input_info("permute"), "weights", "", 1, {1, 1}, {1, 1}, {0, 0}, {0, 0}, false);
topology.add(input_layout_prim, weights_data_prim, surface_input_reorder_prim, conv_input_reorder_prim, conv_prim);
topology.add(input_layout_prim, weights_data_prim, surface_input_reorder_prim, conv_input_reorder_prim, transpose, conv_prim);
ExecutionConfig cfg = get_test_default_config(engine);
cfg.set_property(ov::intel_gpu::queue_type(QueueTypes::out_of_order));
@@ -370,11 +370,10 @@ TEST_P(can_fuse_reorder, surface_input_reorder_batched) {
const auto reorder_prim_id1 = "surface_input_reorder_prim1";
const auto reorder_prim_id2 = "surface_input_reorder_prim2";
auto in_size = tensor{1, 1, 8, 8};
auto weights_size = tensor{32, 1, 8, 8};
auto in_layout = layout(data_types::u8, format::nv12, in_size);
auto in_layout = layout({1, 8, 8, 1}, data_types::u8, format::nv12);
// Set data type the same as input's data type
auto reorder_layout = layout(data_types::u8, format::bfyx, in_size);
auto reorder_layout = layout({1, 8, 8, 1}, data_types::u8, format::bfyx);
auto input_data = engine.allocate_memory({ in_layout });
auto weights_dt = req_data_type == data_types::u8 ? data_types::i8 : req_data_type;
@@ -389,10 +388,11 @@ TEST_P(can_fuse_reorder, surface_input_reorder_batched) {
surface_input_reorder_prim2.input_mem_type = reorder::memory_type::surface;
auto concat = concatenation("concat",{ input_info(reorder_prim_id1),input_info(reorder_prim_id2) }, 0);
auto conv_input_reorder_prim = reorder("reorder_conv", input_info("concat"), req_format, req_data_type);
auto conv_prim = cldnn::convolution("conv", input_info("reorder_conv"), "weights" , "", 1, {1, 1}, {1, 1}, {0, 0}, {0, 0}, false);
auto transpose = permute("permute", input_info("reorder_conv"), {0, 3, 1, 2});
auto conv_prim = cldnn::convolution("conv", input_info("permute"), "weights" , "", 1, {1, 1}, {1, 1}, {0, 0}, {0, 0}, false);
topology.add(input_layout_prim1, input_layout_prim2, weights_data_prim,
surface_input_reorder_prim1, surface_input_reorder_prim2,
surface_input_reorder_prim1, surface_input_reorder_prim2, transpose,
conv_input_reorder_prim, concat, conv_prim);
ExecutionConfig cfg = get_test_default_config(engine);
@@ -14,259 +14,6 @@
using namespace cldnn;
using namespace ::tests;
typedef std::chrono::high_resolution_clock Time;
typedef std::chrono::nanoseconds ns;
typedef std::chrono::duration<double, std::ratio<1, 1000>> ms;
typedef std::chrono::duration<float> fsec;
namespace {
std::vector<unsigned char> createSampleData(int width, int height) {
int data_size = width * (height + height / 2);
auto data = std::vector<unsigned char>(data_size);
srand((unsigned)time(0));
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
data[i * width + j] = (i + j) % 255;
}
}
for (int i = 0; i < height / 2; i++) {
for (int j = 0; j < width; j += 2) {
data[width * height + i * width + j] = (i + j) % 255;
data[width * height + i * width + j + 1] = (i + j) % 255;
}
}
return data;
}
std::vector<float> createReferenceData(std::vector<unsigned char> data, int width, int height, cldnn::format format) {
auto img = std::vector<float>(width * height * 3);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int y_comp = data[i * width + j];
int u_comp = data[width * height + i / 2 * width + ((j >> 1) << 1)];
int v_comp = data[width * height + i / 2 * width + ((j >> 1) << 1) + 1];
float B = (1.164f * (float)(y_comp - 16) + 1.596f * (float)(v_comp - 128));
float G = (1.164f * (float)(y_comp - 16) - 0.813f * (float)(v_comp - 128) - 0.391f * (u_comp - 128));
float R = (1.164f * (float)(y_comp - 16) + 2.018f * (float)(u_comp - 128));
R = std::min(std::max(R, 0.f), 255.f);
G = std::min(std::max(G, 0.f), 255.f);
B = std::min(std::max(B, 0.f), 255.f);
if (format == cldnn::format::bfyx) {
img[j + width * i] = R;
img[j + width * i + width * height] = G;
img[j + width * i + width * height * 2] = B;
} else { //byxf
img[3* width*i + 3 * j] = R;
img[3 * width * i + 3 * j + 1] = G;
img[3 * width*i + 3 * j + 2] = B;
}
}
}
return img;
}
} // namespace
template <typename T>
void start_cl_mem_check_2_inputs(bool is_caching_test) {
device_query query(engine_types::ocl, runtime_types::ocl);
auto devices = query.get_available_devices();
ASSERT_TRUE(!devices.empty());
auto iter = devices.find(std::to_string(device_query::device_id));
auto& device = iter != devices.end() ? iter->second : devices.begin()->second;
auto engine = engine::create(engine_types::ocl, runtime_types::ocl, device);
auto ocl_instance = std::make_shared<OpenCL>(std::dynamic_pointer_cast<ocl::ocl_device>(device)->get_device());
int width = 224;
int height = 224;
cl_int err;
if (!device->get_info().supports_image)
GTEST_SKIP();
auto data = createSampleData(width, height);
cl_image_format image_format;
image_format.image_channel_order = CL_R;
image_format.image_channel_data_type = CL_UNORM_INT8;
cl_image_desc image_desc = { CL_MEM_OBJECT_IMAGE2D, (size_t)width, (size_t)height, 0,
0, 0, 0, 0, 0, { nullptr } };
cl_mem nv12_image_plane_y = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, nullptr, &err);
checkStatus(err, "Creating nv12 image plane_y failed");
image_format.image_channel_order = CL_RG;
image_desc.image_width = width / 2;
image_desc.image_height = height / 2;
image_desc.image_depth = 1;
cl_mem nv12_image_plane_uv = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, nullptr, &err);
checkStatus(err, "Creating nv12 image plane_uv failed");
size_t origin[3] = { 0, 0, 0 };
size_t y_region[3] = { (size_t)width, (size_t)height, 1 };
size_t uv_region[3] = { (size_t)width / 2, (size_t)height / 2, 1 };
err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_y, true, origin, y_region, 0, 0, &data[0], 0, nullptr, nullptr);
checkStatus(err, "Writing nv12 image plane_y failed");
err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_uv, true, origin, uv_region, 0, 0, &data[width * height], 0, nullptr, nullptr);
checkStatus(err, "Writing nv12 image plane_uv failed");
auto input = input_layout("input", { data_types::i8, format::nv12, {1,1,height,width} });
auto input2 = input_layout("input2", { data_types::i8, format::nv12, {1,1,height / 2,width / 2} });
auto output_format = cldnn::format::byxf;
layout output_layout(data_types::f32, output_format, { 1,3,height,width });
auto input_memory = engine->share_image(input.layout, nv12_image_plane_y);
auto input_memory2 = engine->share_image(input2.layout, nv12_image_plane_uv);
topology topology;
topology.add(input);
topology.add(input2);
topology.add(reorder("reorder", input_info("input"), input_info("input2"), output_layout));
cldnn::network::ptr network = get_network(*engine, topology, get_test_default_config(*engine), get_test_stream_ptr(), is_caching_test);
network->set_input_data("input", input_memory);
network->set_input_data("input2", input_memory2);
auto outputs = network->execute();
std::vector<T> reference_results = createReferenceData(data, width, height, output_format);
auto output_prim = outputs.begin()->second.get_memory();
cldnn::mem_lock<T> output_ptr(output_prim, get_test_stream());
int size = width * height * 3;
for (auto i = 0; i < size; i++) {
ASSERT_NEAR(reference_results[i], output_ptr[i], 1.001f);
}
checkStatus(clReleaseMemObject(nv12_image_plane_uv), "clReleaseMemObject");
checkStatus(clReleaseMemObject(nv12_image_plane_y), "clReleaseMemObject");
}
TEST(cl_mem_check, check_2_inputs) {
start_cl_mem_check_2_inputs<float>(false);
}
TEST(export_import_cl_mem_check, check_2_inputs) {
start_cl_mem_check_2_inputs<float>(true);
}
TEST(cl_mem_check, check_input) {
device_query query(engine_types::ocl, runtime_types::ocl);
auto devices = query.get_available_devices();
ASSERT_TRUE(!devices.empty());
auto iter = devices.find(std::to_string(device_query::device_id));
auto& device = iter != devices.end() ? iter->second : devices.begin()->second;
auto engine = engine::create(engine_types::ocl, runtime_types::ocl, device);
auto ocl_instance = std::make_shared<OpenCL>(std::dynamic_pointer_cast<ocl::ocl_device>(device)->get_device());
if (!device->get_info().supports_intel_planar_yuv)
GTEST_SKIP();
int width = 224;
int height = 224;
cl_int err;
auto data = createSampleData(width, height);
cl_image_format image_format;
image_format.image_channel_order = CL_R;
image_format.image_channel_data_type = CL_UNORM_INT8;
cl_image_desc image_desc = { CL_MEM_OBJECT_IMAGE2D, (size_t)width, (size_t)height, 0,
0, 0, 0, 0, 0, { nullptr } };
cl_mem nv12_image_plane_y = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, nullptr, &err);
checkStatus(err, "Creating nv12 image plane_y failed");
image_format.image_channel_order = CL_RG;
image_desc.image_width = width / 2;
image_desc.image_height = height / 2;
cl_mem nv12_image_plane_uv = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, nullptr, &err);
checkStatus(err, "Creating nv12 image plane_uv failed");
size_t origin[3] = { 0, 0, 0 };
size_t y_region[3] = { (size_t)width, (size_t)height, 1 };
size_t uv_region[3] = { (size_t)width / 2, (size_t)height / 2, 1 };
err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_y, true, origin, y_region, 0, 0, &data[0], 0, nullptr, nullptr);
checkStatus(err, "Writing nv12 image plane_y failed");
err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_uv, true, origin, uv_region, 0, 0, &data[width * height], 0, nullptr, nullptr);
checkStatus(err, "Writing nv12 image plane_uv failed");
image_format.image_channel_order = CL_NV12_INTEL;
image_format.image_channel_data_type = CL_UNORM_INT8;
image_desc.image_type = CL_MEM_OBJECT_IMAGE2D;
image_desc.image_width = width;
image_desc.image_height = height;
image_desc.image_array_size = 0;
image_desc.image_row_pitch = 0;
image_desc.image_slice_pitch = 0;
image_desc.num_mip_levels = 0;
image_desc.num_samples = 0;
image_desc.buffer = NULL;
cl_mem img = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE | CL_MEM_HOST_NO_ACCESS | CL_MEM_ACCESS_FLAGS_UNRESTRICTED_INTEL,
&image_format, &image_desc, NULL, &err);
checkStatus(err, "Creating nv12 image failed");
image_desc.image_width = 0;
image_desc.image_height = 0;
image_desc.buffer = img;
image_desc.image_depth = 0;
image_format.image_channel_order = CL_R;
cl_mem img_y = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, nullptr, &err);
checkStatus(err, "Creating nv12 image plane_y failed");
image_desc.image_depth = 1;
image_format.image_channel_order = CL_RG;
cl_mem img_uv = clCreateImage(ocl_instance->_context.get(), CL_MEM_READ_WRITE, &image_format, &image_desc, nullptr, &err);
checkStatus(err, "Creating nv12 image plane_uv failed");
size_t regionY[] = { (size_t)width, (size_t)height, 1 };
size_t regionUV[] = { (size_t)width / 2, (size_t)height / 2, 1 };
err = clEnqueueCopyImage(ocl_instance->_queue.get(), nv12_image_plane_y, img_y, origin, origin, regionY, 0, 0, 0);
checkStatus(err, "clEnqueueCopyImage");
cl_event event_out;
err = clEnqueueCopyImage(ocl_instance->_queue.get(), nv12_image_plane_uv, img_uv, origin, origin, regionUV, 0, 0, &event_out);
checkStatus(err, "clEnqueueCopyImage");
checkStatus(clReleaseMemObject(nv12_image_plane_uv), "clReleaseMemObject");
checkStatus(clReleaseMemObject(nv12_image_plane_y), "clReleaseMemObject");
auto input = input_layout("input", { data_types::i8, format::nv12, {1,1,height,width} });
auto output_format = cldnn::format::byxf;
layout output_layout(data_types::f32, output_format, { 1,3,height,width });
auto input_memory = engine->share_image(input.layout, img);
topology topology;
topology.add(input);
topology.add(reorder("reorder", input_info("input"), output_layout));
network network(*engine, topology, get_test_default_config(*engine));
network.set_input_data("input", input_memory);
auto outputs = network.execute();
std::vector<float> reference_results = createReferenceData(data, width, height, output_format);
auto output_prim = outputs.begin()->second.get_memory();
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
int size = width * height * 3;
for (auto i = 0; i < size; i++) {
ASSERT_NEAR(reference_results[i], output_ptr[i], 1.001f);
}
checkStatus(clReleaseMemObject(img), "clReleaseMemObject");
}
TEST(cl_mem_check, check_write_access_type) {
device_query query(engine_types::ocl, runtime_types::ocl);
auto devices = query.get_available_devices();
@@ -285,7 +32,7 @@ TEST(cl_mem_check, check_write_access_type) {
std::vector<float> src_buffer(values_count);
std::iota(src_buffer.begin(), src_buffer.end(), 0.0f);
cldnn::layout linear_layout = cldnn::layout(cldnn::data_types::f32, cldnn::format::bfyx, cldnn::tensor(1, 1, int32_t(values_count), 1));
cldnn::layout linear_layout{{ov::Dimension(values_count)}, cldnn::data_types::f32, cldnn::format::bfyx};
auto cldnn_mem_src = engine->allocate_memory(linear_layout, cldnn::allocation_type::cl_mem);
{
cldnn::mem_lock<float, cldnn::mem_lock_type::write> lock(cldnn_mem_src, *stream);
@@ -323,7 +70,7 @@ TEST(cl_mem_check, check_read_access_type) {
std::vector<float> src_buffer(values_count);
std::iota(src_buffer.begin(), src_buffer.end(), 0.0f);
cldnn::layout linear_layout = cldnn::layout(cldnn::data_types::f32, cldnn::format::bfyx, cldnn::tensor(1, 1, int32_t(values_count), 1));
cldnn::layout linear_layout{{ov::Dimension(values_count)}, cldnn::data_types::f32, cldnn::format::bfyx};
auto cldnn_mem_src = engine->allocate_memory(linear_layout, cldnn::allocation_type::cl_mem);
{
cldnn::mem_lock<float, cldnn::mem_lock_type::write> lock(cldnn_mem_src, *stream);
@@ -66,8 +66,8 @@ TEST(convert_color, nv12_to_rgb_two_planes_buffer_fp32) {
int width = 224;
int height = 448;
auto input_y = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 1, width, height } });
auto input_uv = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 2, width / 2 , height / 2 } });
auto input_y = engine.allocate_memory({ { 1, height, width, 1 }, data_types::f32, format::bfyx });
auto input_uv = engine.allocate_memory({ { 1, height / 2 , width / 2, 2 }, data_types::f32, format::bfyx});
std::vector<float> input_y_data = rg.generate_random_1d<float>(width * height, 0, 255);
std::vector<float> input_uv_data = rg.generate_random_1d<float>(width * height / 2, 0, 255);
@@ -75,13 +75,14 @@ TEST(convert_color, nv12_to_rgb_two_planes_buffer_fp32) {
set_values(input_y, input_y_data);
set_values(input_uv, input_uv_data);
layout output_layout(data_types::f32, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input_y", input_y->get_layout()));
topology.add(input_layout("input_uv", input_uv->get_layout()));
topology.add(convert_color("convert_color", { input_info("input_y"), input_info("input_uv") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input_y"), input_info("input_uv") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input_y", input_y);
@@ -106,8 +107,8 @@ TEST(convert_color, nv12_to_bgr_two_planes_buffer_fp32) {
int width = 224;
int height = 224;
auto input_y = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 1, width, height } });
auto input_uv = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 2, width / 2 , height / 2 } });
auto input_y = engine.allocate_memory({ { 1, height, width, 1 }, data_types::f32, format::bfyx });
auto input_uv = engine.allocate_memory({ { 1, height / 2 , width / 2, 2 }, data_types::f32, format::bfyx});
std::vector<float> input_y_data = rg.generate_random_1d<float>(width * height, 0, 255);
std::vector<float> input_uv_data = rg.generate_random_1d<float>(width * height / 2, 0, 255);
@@ -115,13 +116,14 @@ TEST(convert_color, nv12_to_bgr_two_planes_buffer_fp32) {
set_values(input_y, input_y_data);
set_values(input_uv, input_uv_data);
layout output_layout(data_types::f32, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input_y", input_y->get_layout()));
topology.add(input_layout("input_uv", input_uv->get_layout()));
topology.add(convert_color("convert_color", { input_info("input_y"), input_info("input_uv") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::BGR,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input_y"), input_info("input_uv") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::BGR,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input_y", input_y);
@@ -147,8 +149,8 @@ TEST(convert_color, nv12_to_rgb_two_planes_buffer_u8) {
int width = 224;
int height = 224;
auto input_y = engine.allocate_memory({ data_types::u8, format::byxf, { 1, 1, width, height } });
auto input_uv = engine.allocate_memory({ data_types::u8, format::byxf, { 1, 2, width / 2 , height / 2 } });
auto input_y = engine.allocate_memory({ { 1, height, width, 1 }, data_types::u8, format::bfyx });
auto input_uv = engine.allocate_memory({ { 1, height / 2 , width / 2, 2 }, data_types::u8, format::bfyx});
std::vector<uint8_t> input_y_data = rg.generate_random_1d<uint8_t>(width * height, 0, 255);
std::vector<uint8_t> input_uv_data = rg.generate_random_1d<uint8_t>(width * height / 2, 0, 255);
@@ -156,13 +158,14 @@ TEST(convert_color, nv12_to_rgb_two_planes_buffer_u8) {
set_values(input_y, input_y_data);
set_values(input_uv, input_uv_data);
layout output_layout(data_types::u8, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input_y", input_y->get_layout()));
topology.add(input_layout("input_uv", input_uv->get_layout()));
topology.add(convert_color("convert_color", { input_info("input_y"), input_info("input_uv") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input_y"), input_info("input_uv") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input_y", input_y);
@@ -188,8 +191,8 @@ TEST(convert_color, nv12_to_rgb_two_planes_buffer_fp16) {
int width = 224;
int height = 224;
auto input_y = engine.allocate_memory({ data_types::f16, format::byxf, { 1, 1, width, height } });
auto input_uv = engine.allocate_memory({ data_types::f16, format::byxf, { 1, 2, width / 2 , height / 2 } });
auto input_y = engine.allocate_memory({ { 1, height, width, 1 }, data_types::f16, format::bfyx });
auto input_uv = engine.allocate_memory({ { 1, height / 2 , width / 2, 2 }, data_types::f16, format::bfyx});
std::vector<FLOAT16> input_y_data = rg.generate_random_1d<FLOAT16>(width * height, 0, 255);
std::vector<FLOAT16> input_uv_data = rg.generate_random_1d<FLOAT16>(width * height / 2, 0, 255);
@@ -197,13 +200,14 @@ TEST(convert_color, nv12_to_rgb_two_planes_buffer_fp16) {
set_values(input_y, input_y_data);
set_values(input_uv, input_uv_data);
layout output_layout(data_types::f16, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input_y", input_y->get_layout()));
topology.add(input_layout("input_uv", input_uv->get_layout()));
topology.add(convert_color("convert_color", { input_info("input_y"), input_info("input_uv") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input_y"), input_info("input_uv") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input_y", input_y);
@@ -231,18 +235,19 @@ TEST(convert_color, nv12_to_rgb_single_plane_buffer_fp32) {
int height = 448;
int input_height = height + height / 2;
auto input = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 1, width, input_height } });
auto input = engine.allocate_memory({{ 1, input_height, width, 1 }, data_types::f32, format::bfyx});
int data_size = width * (height + height / 2);
std::vector<float> input_data = rg.generate_random_1d<float>(data_size, 0, 255);
set_values(input, input_data);
layout output_layout(data_types::f32, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input", input->get_layout()));
topology.add(convert_color("convert_color", { input_info("input") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input", input);
@@ -268,18 +273,19 @@ TEST(convert_color, nv12_to_rgb_single_plane_buffer_u8) {
int height = 448;
int input_height = height + height / 2;
auto input = engine.allocate_memory({ data_types::u8, format::byxf, { 1, 1, width, input_height } });
auto input = engine.allocate_memory({{ 1, input_height, width, 1 }, data_types::u8, format::bfyx});
int data_size = width * (height + height / 2);
std::vector<uint8_t> input_data = rg.generate_random_1d<uint8_t>(data_size, 0, 255);
set_values(input, input_data);
layout output_layout(data_types::u8, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input", input->get_layout()));
topology.add(convert_color("convert_color", { input_info("input") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input", input);
@@ -346,18 +352,19 @@ TEST(convert_color, nv12_to_rgb_two_planes_surface_u8) {
err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image_plane_uv, true, origin, uv_region, 0, 0, &data[width * height], 0, nullptr, nullptr);
checkStatus(err, "Writing nv12 image plane_uv failed");
auto input = input_layout("input", { data_types::u8, format::nv12, { 1, 1, width, height } });
auto input2 = input_layout("input2", { data_types::u8, format::nv12, { 1, 2, width / 2, height / 2} });
auto output_format = cldnn::format::byxf;
layout output_layout(data_types::f32, output_format, { 1, 3, width, height });
auto input = input_layout("input", { { 1, height, width, 1} , data_types::u8, format::nv12 });
auto input2 = input_layout("input2", { { 1, height / 2, width / 2, 2}, data_types::u8, format::nv12 });
auto input_memory = engine->share_image(input.layout, nv12_image_plane_y);
auto input_memory2 = engine->share_image(input2.layout, nv12_image_plane_uv);
topology topology;
topology.add(input);
topology.add(input2);
topology.add(convert_color("convert_color", { input_info("input"), input_info("input2") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::image, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input"), input_info("input2") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::image));
network network(*engine, topology, get_test_default_config(*engine));
network.set_input_data("input", input_memory);
@@ -365,14 +372,14 @@ TEST(convert_color, nv12_to_rgb_two_planes_surface_u8) {
auto outputs = network.execute();
std::vector<float> reference_results(width * height * 3);
createReferenceDataNV12<uint8_t, float>(data.data(), data.data() + height * width, reference_results.data(),
1, height, width, height * width, height * width / 2, true);
std::vector<uint8_t> reference_results(width * height * 3);
createReferenceDataNV12<uint8_t, uint8_t>(data.data(), data.data() + height * width, reference_results.data(),
1, height, width, height * width, height * width / 2, true);
auto output_prim = outputs.begin()->second.get_memory();
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
cldnn::mem_lock<uint8_t> output_ptr(output_prim, get_test_stream());
for (size_t i = 0; i < reference_results.size(); i++) {
ASSERT_NEAR(reference_results[i], output_ptr[i], 1.001f);
ASSERT_EQ(reference_results[i], output_ptr[i]);
}
checkStatus(clReleaseMemObject(nv12_image_plane_uv), "clReleaseMemObject");
checkStatus(clReleaseMemObject(nv12_image_plane_y), "clReleaseMemObject");
@@ -415,29 +422,30 @@ TEST(convert_color, nv12_to_rgb_single_plane_surface_u8) {
err = clEnqueueWriteImage(ocl_instance->_queue.get(), nv12_image, true, origin, y_region, 0, 0, &input_data[0], 0, nullptr, nullptr);
checkStatus(err, "Writing nv12 image failed");
auto input = input_layout("input", { data_types::u8, format::nv12, { 1, 1, width, input_height } });
auto output_format = cldnn::format::byxf;
layout output_layout(data_types::f32, output_format, { 1, 3, width, height });
auto input = input_layout("input", {{ 1, input_height, width, 1 }, data_types::u8, format::nv12});
auto input_memory = engine->share_image(input.layout, nv12_image);
topology topology;
topology.add(input);
topology.add(convert_color("convert_color", { input_info("input") }, cldnn::convert_color::color_format::NV12, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::image, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input") },
cldnn::convert_color::color_format::NV12,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::image));
network network(*engine, topology, get_test_default_config(*engine));
network.set_input_data("input", input_memory);
auto outputs = network.execute();
std::vector<float> reference_results(width * height * 3);
createReferenceDataNV12<uint8_t, float>(input_data.data(), input_data.data() + height * width, reference_results.data(),
std::vector<uint8_t> reference_results(width * height * 3);
createReferenceDataNV12<uint8_t, uint8_t>(input_data.data(), input_data.data() + height * width, reference_results.data(),
1, height, width, input_height * width, input_height * width, true);
auto output_prim = outputs.begin()->second.get_memory();
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
cldnn::mem_lock<uint8_t> output_ptr(output_prim, get_test_stream());
for (size_t i = 0; i < reference_results.size(); i++) {
ASSERT_NEAR(reference_results[i], output_ptr[i], 1.001f);
ASSERT_EQ(reference_results[i], output_ptr[i]);
}
checkStatus(clReleaseMemObject(nv12_image), "clReleaseMemObject");
}
@@ -498,9 +506,9 @@ TEST(convert_color, i420_to_rgb_three_planes_buffer_fp32) {
int width = 224;
int height = 448;
auto input_y = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 1, width, height } });
auto input_u = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 1, width / 2 , height / 2 } });
auto input_v = engine.allocate_memory({ data_types::f32, format::byxf, { 1, 1, width / 2 , height / 2 } });
auto input_y = engine.allocate_memory({ { 1, height, width, 1 }, data_types::f32, format::bfyx });
auto input_u = engine.allocate_memory({ { 1, height / 2 , width / 2, 1 }, data_types::f32, format::bfyx });
auto input_v = engine.allocate_memory({ { 1, height / 2 , width / 2, 1 }, data_types::f32, format::bfyx });
std::vector<float> input_y_data = rg.generate_random_1d<float>(width * height, 0, 255);
std::vector<float> input_u_data = rg.generate_random_1d<float>(width * height / 4, 0, 255);
@@ -510,14 +518,15 @@ TEST(convert_color, i420_to_rgb_three_planes_buffer_fp32) {
set_values(input_u, input_u_data);
set_values(input_v, input_v_data);
layout output_layout(data_types::f32, cldnn::format::byxf, { 1, 3, width, height });
topology topology;
topology.add(input_layout("input_y", input_y->get_layout()));
topology.add(input_layout("input_u", input_u->get_layout()));
topology.add(input_layout("input_v", input_v->get_layout()));
topology.add(convert_color("convert_color", { input_info("input_y"), input_info("input_u"), input_info("input_v") }, cldnn::convert_color::color_format::I420, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input_y"), input_info("input_u"), input_info("input_v") },
cldnn::convert_color::color_format::I420,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::buffer));
network network(engine, topology, get_test_default_config(engine));
network.set_input_data("input_y", input_y);
@@ -590,11 +599,9 @@ void test_convert_color_i420_to_rgb_three_planes_surface_u8(bool is_caching_test
err = clEnqueueWriteImage(ocl_instance->_queue.get(), i420_image_plane_v, true, origin, uv_region, 0, 0, &data[width * (height + height / 4)], 0, nullptr, nullptr);
checkStatus(err, "Writing i420 image plane_v failed");
auto input = input_layout("input", { data_types::u8, format::nv12, { 1, 1, width, height } });
auto input2 = input_layout("input2", { data_types::u8, format::nv12, { 1, 1, width / 2, height / 2 } });
auto input3 = input_layout("input3", { data_types::u8, format::nv12, { 1, 1, width / 2, height / 2 } });
auto output_format = cldnn::format::byxf;
layout output_layout(data_types::f32, output_format, { 1, 3, width, height });
auto input = input_layout("input", { { 1, height, width, 1 }, data_types::u8, format::nv12, });
auto input2 = input_layout("input2", { { 1, height / 2, width / 2, 1 }, data_types::u8, format::nv12 });
auto input3 = input_layout("input3", { { 1, height / 2, width / 2, 1 }, data_types::u8, format::nv12 });
auto input_memory = engine->share_image(input.layout, i420_image_plane_y);
auto input_memory2 = engine->share_image(input2.layout, i420_image_plane_u);
@@ -604,8 +611,11 @@ void test_convert_color_i420_to_rgb_three_planes_surface_u8(bool is_caching_test
topology.add(input);
topology.add(input2);
topology.add(input3);
topology.add(convert_color("convert_color", { input_info("input"), input_info("input2"), input_info("input3") }, cldnn::convert_color::color_format::I420, cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::image, output_layout));
topology.add(convert_color("convert_color",
{ input_info("input"), input_info("input2"), input_info("input3") },
cldnn::convert_color::color_format::I420,
cldnn::convert_color::color_format::RGB,
cldnn::convert_color::memory_type::image));
cldnn::network::ptr network = get_network(*engine, topology, get_test_default_config(*engine), get_test_stream_ptr(), is_caching_test);
@@ -615,14 +625,14 @@ void test_convert_color_i420_to_rgb_three_planes_surface_u8(bool is_caching_test
auto outputs = network->execute();
std::vector<float> reference_results(width * height * 3);
createReferenceDataI420<T, float>(data.data(), data.data() + height * width, data.data() + width * (height + height / 4), reference_results.data(),
std::vector<uint8_t> reference_results(width * height * 3);
createReferenceDataI420<T, uint8_t>(data.data(), data.data() + height * width, data.data() + width * (height + height / 4), reference_results.data(),
1, height, width, height * width, height * width / 2, true);
auto output_prim = outputs.begin()->second.get_memory();
cldnn::mem_lock<float> output_ptr(output_prim, get_test_stream());
cldnn::mem_lock<uint8_t> output_ptr(output_prim, get_test_stream());
for (size_t i = 0; i < reference_results.size(); i++) {
ASSERT_NEAR(reference_results[i], output_ptr[i], 1.001f);
ASSERT_EQ(reference_results[i], output_ptr[i]) << " i = " << i;
}
checkStatus(clReleaseMemObject(i420_image_plane_y), "clReleaseMemObject");
checkStatus(clReleaseMemObject(i420_image_plane_u), "clReleaseMemObject");
@@ -1,61 +0,0 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "test_utils.h"
#include "intel_gpu/graph/serialization/binary_buffer.hpp"
#include "intel_gpu/graph/serialization/string_serializer.hpp"
#include "intel_gpu/graph/serialization/utils.hpp"
using namespace cldnn;
using namespace ::tests;
struct ie_layout_serialization_test : testing::TestWithParam<InferenceEngine::Layout> {
void run_test() {
InferenceEngine::Layout test_layout = GetParam();
membuf mem_buf;
{
std::ostream out_mem(&mem_buf);
BinaryOutputBuffer ob = BinaryOutputBuffer(out_mem);
std::stringstream ss;
ss << test_layout;
ob << ss.str();
}
{
std::istream in_mem(&mem_buf);
BinaryInputBuffer ib = BinaryInputBuffer(in_mem, get_test_engine());
std::string str_layout;
ib >> str_layout;
EXPECT_EQ(cldnn::serial_util::layout_from_string(str_layout), test_layout);
}
}
};
TEST_P(ie_layout_serialization_test, basic) {
run_test();
}
INSTANTIATE_TEST_SUITE_P(
gpu_serialization,
ie_layout_serialization_test,
testing::Values(InferenceEngine::Layout::ANY,
InferenceEngine::Layout::NCHW,
InferenceEngine::Layout::NHWC,
InferenceEngine::Layout::NCDHW,
InferenceEngine::Layout::NDHWC,
InferenceEngine::Layout::OIHW,
InferenceEngine::Layout::GOIHW,
InferenceEngine::Layout::OIDHW,
InferenceEngine::Layout::GOIDHW,
InferenceEngine::Layout::SCALAR,
InferenceEngine::Layout::C,
InferenceEngine::Layout::CHW,
InferenceEngine::Layout::HWC,
InferenceEngine::Layout::HW,
InferenceEngine::Layout::NC,
InferenceEngine::Layout::CN,
InferenceEngine::Layout::BLOCKED)
);
@@ -26,7 +26,7 @@ void create_plugin(std::shared_ptr<ov::IPlugin>& plugin);
*
* @return Original remote context
*/
const ov::SoPtr<ov::IRemoteContext>& get_hardware_context(const ov::SoPtr<ov::IRemoteContext>& context);
ov::SoPtr<ov::IRemoteContext> get_hardware_context(const ov::SoPtr<ov::IRemoteContext>& context);
/**
* @brief Get wrapped remote tensor
@@ -35,7 +35,7 @@ const ov::SoPtr<ov::IRemoteContext>& get_hardware_context(const ov::SoPtr<ov::IR
*
* @return Original remote tensor
*/
const ov::SoPtr<ov::ITensor>& get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor);
ov::SoPtr<ov::ITensor> get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor, bool unwrap = false);
} // namespace proxy
} // namespace ov
+7 -2
View File
@@ -7,6 +7,7 @@
#include <memory>
#include <openvino/runtime/iremote_tensor.hpp>
#include "openvino/proxy/plugin.hpp"
#include "openvino/runtime/itensor.hpp"
#include "openvino/runtime/make_tensor.hpp"
#include "openvino/runtime/remote_context.hpp"
@@ -57,7 +58,7 @@ ov::SoPtr<ov::ITensor> ov::proxy::InferRequest::get_tensor(const ov::Output<cons
}
void ov::proxy::InferRequest::set_tensor(const ov::Output<const ov::Node>& port, const ov::SoPtr<ov::ITensor>& tensor) {
m_infer_request->set_tensor(port, tensor);
m_infer_request->set_tensor(port, ov::proxy::get_hardware_tensor(tensor, true));
}
std::vector<ov::SoPtr<ov::ITensor>> ov::proxy::InferRequest::get_tensors(const ov::Output<const ov::Node>& port) const {
@@ -75,7 +76,11 @@ std::vector<ov::SoPtr<ov::ITensor>> ov::proxy::InferRequest::get_tensors(const o
void ov::proxy::InferRequest::set_tensors(const ov::Output<const ov::Node>& port,
const std::vector<ov::SoPtr<ov::ITensor>>& tensors) {
return m_infer_request->set_tensors(port, tensors);
std::vector<ov::SoPtr<ov::ITensor>> hw_tensors;
for (auto& tensor : tensors) {
hw_tensors.push_back(ov::proxy::get_hardware_tensor(tensor, true));
}
return m_infer_request->set_tensors(port, hw_tensors);
}
std::vector<ov::SoPtr<ov::IVariableState>> ov::proxy::InferRequest::query_state() const {
+1 -1
View File
@@ -75,6 +75,6 @@ const ov::SoPtr<ov::IRemoteContext>& ov::proxy::RemoteContext::get_hardware_cont
return context;
}
const ov::SoPtr<ov::IRemoteContext>& ov::proxy::get_hardware_context(const ov::SoPtr<ov::IRemoteContext>& context) {
ov::SoPtr<ov::IRemoteContext> ov::proxy::get_hardware_context(const ov::SoPtr<ov::IRemoteContext>& context) {
return ov::proxy::RemoteContext::get_hardware_context(context);
}
+20 -5
View File
@@ -7,6 +7,10 @@
#include <memory>
#include "openvino/proxy/plugin.hpp"
#include "openvino/runtime/itensor.hpp"
#include "openvino/runtime/make_tensor.hpp"
#include "openvino/runtime/so_ptr.hpp"
#include "remote_utils.hpp"
namespace {
std::shared_ptr<ov::IRemoteTensor> cast_tensor(const ov::SoPtr<ov::ITensor>& tensor) {
@@ -59,12 +63,23 @@ const ov::Strides& ov::proxy::RemoteTensor::get_strides() const {
return m_tensor->get_strides();
}
const ov::SoPtr<ov::ITensor>& ov::proxy::RemoteTensor::get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor) {
ov::SoPtr<ov::ITensor> ov::proxy::RemoteTensor::get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor, bool unwrap) {
ov::SoPtr<ov::ITensor> hw_tensor = tensor;
if (auto remote_tensor = std::dynamic_pointer_cast<ov::proxy::RemoteTensor>(tensor._ptr))
return remote_tensor->m_tensor;
return tensor;
hw_tensor = remote_tensor->m_tensor;
if (unwrap) {
if (auto wrapper = std::dynamic_pointer_cast<ov::RemoteBlobTensor>(hw_tensor._ptr)) {
auto blob = ov::get_hardware_blob(wrapper->blob.get());
if (auto tensor_holder = dynamic_cast<ov::legacy_convert::TensorHolder*>(blob)) {
hw_tensor = tensor_holder->get_tensor();
}
}
}
return hw_tensor;
}
const ov::SoPtr<ov::ITensor>& ov::proxy::get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor) {
return ov::proxy::RemoteTensor::get_hardware_tensor(tensor);
ov::SoPtr<ov::ITensor> ov::proxy::get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor, bool unwrap) {
return ov::proxy::RemoteTensor::get_hardware_tensor(tensor, unwrap);
}
+1 -1
View File
@@ -36,7 +36,7 @@ public:
const ov::Strides& get_strides() const override;
static const ov::SoPtr<ov::ITensor>& get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor);
static ov::SoPtr<ov::ITensor> get_hardware_tensor(const ov::SoPtr<ov::ITensor>& tensor, bool unwrap);
private:
mutable std::string m_name;