Introduce data accessor function for infer in IStaticShapeInfer (#15574)
* Tensor accessor for shape inference - as functor for getting data from tensor vector or map. - as lambda in GPU plugin on tile op * Make tensor data adapter pure virtual - function accessor to data returns pointer to interface * Refactor tensor data accessor and adapter * Extract memory adapter make it GPU graph internal - can't be part of GPU runtime memory core dev API not visible there * Expand IStaticShapeInfer by port map - update factory map for new infer interface with port map information - add bit util to generate bit mask use it in PortMask * Pass tensor accessor as reference not fun object - Add cldnn data adapter and accessor - Reduce dynamic allocations in data accessors * Fix compilation issues * Use ov::Tensor for data accessor - remove data adapters are they not required * Update comments * Fix build issues * Fix tile shape infer test * Add empty null tensor accessor as specialization * Apply style formatting * Move data accessor from dev API to shape inference * Fix linking issues
This commit is contained in:
84
src/plugins/intel_gpu/src/graph/include/memory_accessor.hpp
Normal file
84
src/plugins/intel_gpu/src/graph/include/memory_accessor.hpp
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (C) 2018-2023 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "intel_gpu/runtime/memory.hpp"
|
||||
#include "tensor_data_accessor.hpp"
|
||||
|
||||
namespace cldnn {
|
||||
|
||||
/**
|
||||
* @brief CLDNN memory accessor implementing ov::ITensorAccessor to get data as tensor from CLDNN container.
|
||||
*/
|
||||
struct MemoryAccessor : public ov::ITensorAccessor {
|
||||
using container_type = std::map<size_t, memory::ptr>; //!< Alias to cldnn memory map.
|
||||
|
||||
/**
|
||||
* @brief Construct a new Memory Accessor without custom callback.
|
||||
*
|
||||
* @param ptrs Pointer to CLDNN memory container pointers.
|
||||
* @param stream CLDNN stream used for memory locks.
|
||||
*/
|
||||
MemoryAccessor(const container_type* ptrs, const stream& stream)
|
||||
: m_ptrs{ptrs},
|
||||
m_stream{stream},
|
||||
m_clbk{},
|
||||
m_accessed_data{} {}
|
||||
|
||||
/**
|
||||
* @brief Construct a new Memory Accessor with custom callback function.
|
||||
*
|
||||
* @param ptrs Pointer to CLDNN memory container pointers.
|
||||
* @param stream CLDNN stream used for memory locks.
|
||||
* @param clbk Function object for custom callback when accessing data and not found in CLDNN memories.
|
||||
*/
|
||||
MemoryAccessor(const container_type* ptrs, const stream& stream, std::function<const ov::Tensor(size_t)> clbk)
|
||||
: m_ptrs{ptrs},
|
||||
m_stream{stream},
|
||||
m_clbk{std::move(clbk)},
|
||||
m_accessed_data{} {}
|
||||
|
||||
~MemoryAccessor() {
|
||||
unlock_current_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get data from CLDNN memory container or by custom callback function if defined.
|
||||
*
|
||||
* Data get from CLDNN memory are locket until this accessor will be deleted or access new data.
|
||||
*
|
||||
* @param port Number of operator port to access data.
|
||||
* @return Tensor to data.
|
||||
*/
|
||||
ov::Tensor operator()(size_t port) const override {
|
||||
unlock_current_data();
|
||||
m_accessed_data = nullptr;
|
||||
|
||||
const auto t_iter = m_ptrs->find(port);
|
||||
if (t_iter != m_ptrs->cend()) {
|
||||
m_accessed_data = t_iter->second;
|
||||
return {data_type_to_element_type(m_accessed_data->get_layout().data_type),
|
||||
m_accessed_data->get_layout().get_shape(),
|
||||
m_accessed_data->lock(m_stream, mem_lock_type::read)};
|
||||
} else if (m_clbk) {
|
||||
return m_clbk(port);
|
||||
} else {
|
||||
return ov::make_tensor_accessor()(port);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void unlock_current_data() const {
|
||||
if (m_accessed_data) {
|
||||
m_accessed_data->unlock(m_stream);
|
||||
}
|
||||
}
|
||||
|
||||
const container_type* m_ptrs; //!< Pointer to CLDNN memory pointers with op data.
|
||||
const stream& m_stream; //!< Current stream used for data lock.
|
||||
std::function<ov::Tensor(size_t)> m_clbk; //!< Function object to get data if not in m_ptrs.
|
||||
mutable memory::ptr m_accessed_data; //!< Pointer to current accessed data.
|
||||
};
|
||||
} // namespace cldnn
|
||||
@@ -6,12 +6,14 @@
|
||||
#include "tile_shape_inference.hpp"
|
||||
|
||||
#include "primitive_type_base.h"
|
||||
#include "memory_accessor.hpp"
|
||||
#include "intel_gpu/runtime/memory.hpp"
|
||||
#include "intel_gpu/runtime/format.hpp"
|
||||
#include "json_object.h"
|
||||
#include <string>
|
||||
|
||||
namespace cldnn {
|
||||
|
||||
GPU_DEFINE_PRIMITIVE_TYPE_ID(tile)
|
||||
|
||||
layout tile_inst::calc_output_layout(tile_node const& node, kernel_impl_params const& impl_param) {
|
||||
@@ -44,36 +46,25 @@ std::vector<layout> tile_inst::calc_output_layouts(tile_node const& /*node*/, co
|
||||
ShapeType repeats_shape = impl_param.input_layouts.size() == 2 ? impl_param.get_input_layout(1).get<ShapeType>()
|
||||
: ov::Shape{ desc->repeats.size() };
|
||||
ov::op::v0::Tile op;
|
||||
std::vector<ShapeType> output_shapes;
|
||||
std::vector<ShapeType> input_shapes = {
|
||||
input0_layout.get<ShapeType>(),
|
||||
repeats_shape
|
||||
};
|
||||
|
||||
auto& constant_mem = impl_param.memory_deps;
|
||||
if (desc->input_size() == 2) {
|
||||
if (constant_mem.count(1)) {
|
||||
auto repeats_mem = constant_mem.at(1);
|
||||
cldnn::mem_lock<uint8_t, mem_lock_type::read> repeats_lock(repeats_mem, impl_param.get_stream());
|
||||
const auto& layout = repeats_mem->get_layout();
|
||||
const auto repeats_tensor =
|
||||
ov::Tensor(data_type_to_element_type(layout.data_type), layout.get_shape(), repeats_lock.data());
|
||||
output_shapes = ov::op::v0::shape_infer(&op, input_shapes, {{1, repeats_tensor}});
|
||||
} else if (repeats_shape.size() > 0 && repeats_shape[0].is_static()) {
|
||||
output_shapes = { ov::PartialShape::dynamic(std::max<size_t>(input_shapes[0].size(), repeats_shape[0].get_length())) };
|
||||
} else {
|
||||
output_shapes = { ov::PartialShape::dynamic() };
|
||||
}
|
||||
} else {
|
||||
auto repeats_data = desc->repeats;
|
||||
const auto repeats_tensor =
|
||||
ov::Tensor(data_type_to_element_type(data_types::i64), repeats_shape.to_shape(), repeats_data.data());
|
||||
output_shapes = ov::op::v0::shape_infer(&op, input_shapes, {{1, repeats_tensor}});
|
||||
}
|
||||
auto repeats = desc->repeats;
|
||||
const auto data_accessor =
|
||||
MemoryAccessor(&impl_param.memory_deps, impl_param.prog->get_stream(), [&repeats, &repeats_shape](size_t port) {
|
||||
return (port == 1 && repeats.data()) ? ov::Tensor(data_type_to_element_type(data_types::i64),
|
||||
repeats_shape.to_shape(),
|
||||
repeats.data())
|
||||
: ov::Tensor();
|
||||
});
|
||||
|
||||
std::vector<ShapeType> output_shapes = ov::op::v0::shape_infer(&op, input_shapes, data_accessor);
|
||||
|
||||
format output_format = format::adjust_to_rank(input0_layout.format, output_shapes[0].size());
|
||||
|
||||
return { layout{output_shapes[0], output_type, output_format} };
|
||||
return {layout{output_shapes[0], output_type, output_format}};
|
||||
}
|
||||
|
||||
template std::vector<layout> tile_inst::calc_output_layouts<ov::PartialShape>(tile_node const& node, const kernel_impl_params& impl_param);
|
||||
|
||||
Reference in New Issue
Block a user