1 // Copyright (C) 2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
13 #include <ie_layers.h>
14 #include <ie_algorithm.hpp>
15 #include "ie_const_infer_impl.hpp"
16 #include "ie_parallel.hpp"
18 namespace InferenceEngine {
19 namespace ShapeInfer {
22 size_t dataLength = 1;
24 size_t indexRange = 0;
25 size_t numDictionaries = 1;
28 template<typename data_t>
30 gather(data_t* src_dataIdx, const Blob::CPtr& indexes, const Blob::CPtr& dictionary, const Blob::Ptr& output,
31 const GatherParams& p) {
32 size_t src_dataIdxSize = indexes->size();
33 size_t dataSize = sizeof(float) * p.dataLength;
35 const float* src_dataDict =
36 dictionary->cbuffer().as<const float*>() + dictionary->getTensorDesc().getBlockingDesc().getOffsetPadding();
37 float* dst_data = output->cbuffer().as<float*>() + output->getTensorDesc().getBlockingDesc().getOffsetPadding();
38 src_dataIdx += indexes->getTensorDesc().getBlockingDesc().getOffsetPadding();
41 parallel_for(src_dataIdxSize, [&](size_t i) {
42 int idx = static_cast<int>(src_dataIdx[i]);
45 details::clipping(&idx, 0, p.indexRange);
47 // Copying data to destination from Dictionary
48 ie_memcpy(&dst_data[p.dataLength * i],
49 output->byteSize() - (p.dataLength * i),
50 &src_dataDict[p.dataLength * idx],
54 parallel_for(src_dataIdxSize, [&](size_t i) {
55 int idx = static_cast<int>(src_dataIdx[i]);
58 details::clipping(&idx, 0, p.indexRange);
60 // Copying data to destination from Dictionary
61 for (size_t j = 0; j < p.numDictionaries; j++) {
62 ie_memcpy(&dst_data[p.dataLength * (i + j * src_dataIdxSize)],
63 output->byteSize() - (p.dataLength * (i + j * src_dataIdxSize)),
64 &src_dataDict[p.dataLength * (idx + j * p.indexRange)],
72 *@brief Implementation of Const inference for Gather layer
74 class GatherConstInfer : public ConstInferImpl {
76 explicit GatherConstInfer(const std::string& type) : ConstInferImpl(type) {}
78 void inferImpl(const std::vector<Blob::CPtr>& inData,
79 const std::map<std::string, std::string>& params,
80 const std::map<std::string, Blob::Ptr>& blobs,
81 std::vector<Blob::Ptr>& outData) override {
84 layer.params = params;
87 const size_t GATHER_DICTIONARY = 0;
88 const size_t GATHER_INDEXES = 1;
90 if (inData.size() != 2 || outData.empty())
91 THROW_IE_EXCEPTION << " Incorrect number of input/output edges!";
93 Precision inIdxPrecision = inData[GATHER_INDEXES]->getTensorDesc().getPrecision();
94 if (inIdxPrecision != Precision::FP32 &&
95 inIdxPrecision != Precision::I32 &&
96 inIdxPrecision != Precision::U16 &&
97 inIdxPrecision != Precision::I16 &&
98 inIdxPrecision != Precision::U8 &&
99 inIdxPrecision != Precision::I8)
100 THROW_IE_EXCEPTION << " Incorrect input precision. Only FP32|I32|U16|I16|U8|I8 are supported!";
102 // Remove redundant dimensions
103 const SizeVector& dictionary_dims = inData[GATHER_DICTIONARY]->getTensorDesc().getDims();
104 size_t actualAxis = 0;
105 SizeVector dims_actual;
106 for (size_t i = 0; i < dictionary_dims.size(); i++) {
107 if (dictionary_dims[i] > 1) {
108 for (size_t j = i; j < dictionary_dims.size(); j++)
109 dims_actual.push_back(dictionary_dims[j]);
114 if (dims_actual.size() == 0)
115 THROW_IE_EXCEPTION << " Incorrect input parameters dimension!";
118 p.axis = static_cast<int>(layer.GetParamAsInt("axis"));
119 // Dictionary must be at least rank axis + 1
120 if (p.axis > 0 && dims_actual.size() < (1 + p.axis))
121 THROW_IE_EXCEPTION << " Incorrect input parameters dimensions and axis number!";
122 else if (p.axis < 0 && (static_cast<int>(dims_actual.size()) + p.axis) < 0)
123 THROW_IE_EXCEPTION << " Incorrect input parameters dimensions and axis number!";
126 p.axis += dims_actual.size();
128 // Find number of dictionaries, index range and data length
129 for (size_t i = 0; i < p.axis; i++)
130 p.numDictionaries *= dims_actual[i];
131 p.indexRange = dims_actual[p.axis];
132 for (size_t i = p.axis + 1; i < dims_actual.size(); i++)
133 p.dataLength *= dims_actual[i];
135 if (p.dataLength == 0)
136 THROW_IE_EXCEPTION << " Incorrect input parameters dimension!";
139 switch (inData[GATHER_INDEXES]->precision()) {
140 case Precision::FP32:
141 gather(inData[GATHER_INDEXES]->cbuffer().as<const float*>(), inData[GATHER_INDEXES],
142 inData[GATHER_DICTIONARY], outData[0], p);
145 gather(inData[GATHER_INDEXES]->cbuffer().as<const int32_t*>(), inData[GATHER_INDEXES],
146 inData[GATHER_DICTIONARY], outData[0], p);
149 gather(inData[GATHER_INDEXES]->cbuffer().as<const uint16_t*>(), inData[GATHER_INDEXES],
150 inData[GATHER_DICTIONARY], outData[0], p);
153 gather(inData[GATHER_INDEXES]->cbuffer().as<const int16_t*>(), inData[GATHER_INDEXES],
154 inData[GATHER_DICTIONARY], outData[0], p);
157 gather(inData[GATHER_INDEXES]->cbuffer().as<const uint8_t*>(), inData[GATHER_INDEXES],
158 inData[GATHER_DICTIONARY], outData[0], p);
161 gather(inData[GATHER_INDEXES]->cbuffer().as<const int8_t*>(), inData[GATHER_INDEXES],
162 inData[GATHER_DICTIONARY], outData[0], p);
165 THROW_IE_EXCEPTION << " Unsupported precision!";
170 } // namespace ShapeInfer
171 } // namespace InferenceEngine