[CPU] EmbeddingBagOffsetsSum, EmbeddingBagPackedSum, EmbeddingSegmentsSum operations. (#576)
* [CPU] EmbeddingBagOffsetsSum, EmbeddingBagPackedSum, EmbeddingSegmentsSum operations. * Performance fix * Perf v2 * Code style
This commit is contained in:
1 parent
4c44ce9795
commit
4f6c976add
26 files changed
+1706
-1
No files matched your search
@@ -53,6 +53,10 @@ set(LAYERS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/depth_to_space.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/detectionoutput.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/detectionoutput_onnx.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/embedding_bag_offset_sum.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/embedding_bag_packed_sum.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/embedding_bag_sum.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/embedding_segments_sum.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/extract_image_patches.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/fill.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/nodes/gather.cpp
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "embedding_bag_sum.hpp"
|
||||
#include "ie_parallel.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace InferenceEngine {
|
||||
namespace Extensions {
|
||||
namespace Cpu {
|
||||
|
||||
class EmbeddingBagOffsetsSumImpl: public MKLDNNEmbeddingBagSum {
|
||||
public:
|
||||
explicit EmbeddingBagOffsetsSumImpl(const CNNLayer* layer) :
|
||||
MKLDNNEmbeddingBagSum(layer, 3lu, 1lu, 4lu, 3lu) {
|
||||
auto indicesData = layer->insData[INDICES_IDX].lock();
|
||||
if (indicesData == nullptr)
|
||||
THROW_IE_EXCEPTION << "'" << layer->name << "' layer has nullable indices data.";
|
||||
if (indicesData->getTensorDesc().getDims().size() != 1)
|
||||
THROW_IE_EXCEPTION << "'" << layer->name << "' layer has indices data with invalid shape.";
|
||||
|
||||
auto offsetsData = layer->insData[OFFSETS_IDX].lock();
|
||||
if (offsetsData == nullptr)
|
||||
THROW_IE_EXCEPTION << "'" << layer->name << "' layer has invalid offsets data.";
|
||||
if (offsetsData->getTensorDesc().getDims().size() != 1)
|
||||
THROW_IE_EXCEPTION << "'" << layer->name << "' layer's offsets data has invalid shape.";
|
||||
|
||||
_indicesLen = indicesData->getTensorDesc().getDims()[0];
|
||||
_offsetsLen = offsetsData->getTensorDesc().getDims()[0];
|
||||
}
|
||||
|
||||
StatusCode execute(
|
||||
std::vector<Blob::Ptr>& inputs,
|
||||
std::vector<Blob::Ptr>& outputs,
|
||||
ResponseDesc* resp) noexcept override {
|
||||
switch (inputs[0]->getTensorDesc().getPrecision()) {
|
||||
case Precision::FP32: {
|
||||
return processData<PrecisionTrait<Precision::FP32>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
case Precision::I8: {
|
||||
return processData<PrecisionTrait<Precision::I8>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
case Precision::U8: {
|
||||
return processData<PrecisionTrait<Precision::U8>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
case Precision::I32: {
|
||||
return processData<PrecisionTrait<Precision::I32>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
default: {
|
||||
if (resp) {
|
||||
std::string errorMsg = "EmbeddingBagSum layer does not support embedding table precision '"
|
||||
+ std::string(inputs[0]->getTensorDesc().getPrecision().name()) + "'";
|
||||
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
}
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
StatusCode processData(
|
||||
std::vector<Blob::Ptr>& inputs,
|
||||
std::vector<Blob::Ptr>& outputs,
|
||||
ResponseDesc* resp) noexcept {
|
||||
switch (inputs[1]->getTensorDesc().getPrecision()) {
|
||||
case Precision::I32: {
|
||||
return processData<T, PrecisionTrait<Precision::I32>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
case Precision::I64: {
|
||||
return processData<T, PrecisionTrait<Precision::I64>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
case Precision::U64: {
|
||||
return processData<T, PrecisionTrait<Precision::U64>::value_type>(inputs, outputs, resp);
|
||||
}
|
||||
default: {
|
||||
if (resp) {
|
||||
std::string errorMsg = "EmbeddingBagSum layer does not support indices precision '"
|
||||
+ std::string(inputs[1]->getTensorDesc().getPrecision().name()) + "'";
|
||||
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
}
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename I>
|
||||
StatusCode processData(
|
||||
std::vector<Blob::Ptr>& inputs,
|
||||
std::vector<Blob::Ptr>& outputs,
|
||||
ResponseDesc* resp) noexcept {
|
||||
std::string errorMsg;
|
||||
std::string msgPrefix = std::string("Layer EmbeddingBagOffsetsSum with name '") + _layerName + "' ";
|
||||
|
||||
const T* srcData = inputs[0]->cbuffer().as<const T*>() +
|
||||
inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
T* dstData = outputs[0]->buffer().as<T*>() +
|
||||
outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
|
||||
const I* indicesData = inputs[INDICES_IDX]->cbuffer().as<const I*>();
|
||||
|
||||
const I* offsetsData = inputs[OFFSETS_IDX]->cbuffer().as<const I*>();
|
||||
int64_t defaultIndex = -1;
|
||||
if (inputs.size() > DEFAULT_INDEX_IDX) {
|
||||
defaultIndex = (int64_t)inputs[DEFAULT_INDEX_IDX]->cbuffer().as<const I*>()[0];
|
||||
if (defaultIndex < 0 || defaultIndex >= _indicesLen) {
|
||||
std::string msg = "Invalid default index: " + std::to_string(defaultIndex);
|
||||
msg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
const T* weightsData = nullptr;
|
||||
if (_withWeights)
|
||||
weightsData = inputs[PER_SAMPLE_WEIGHTS_IDX]->cbuffer().as<const T*>();
|
||||
|
||||
const auto& inDataDims = inputs[0]->getTensorDesc().getDims();
|
||||
const size_t IN_BAGS_DEPTH = inDataDims.size() - 1;
|
||||
|
||||
const size_t OUTPUT_BAGS_NUM = outputs[0]->getTensorDesc().getDims()[0];
|
||||
|
||||
std::function<void(size_t, const I*&, size_t&, size_t&, bool&)> get_idx =
|
||||
[&](size_t embIndex, const I*& indicesRef, size_t& outSize, size_t& weightsIdx, bool& withWeights) {
|
||||
if (embIndex >= _offsetsLen) {
|
||||
errorMsg = msgPrefix + "has invalid embedding bag index.";
|
||||
return;
|
||||
}
|
||||
if (offsetsData[embIndex] >= _indicesLen) {
|
||||
errorMsg = msgPrefix + ". Offset value exceeds indices size in the model.\noffset: "
|
||||
+ std::to_string(offsetsData[embIndex]) + "; indices size: " + std::to_string(_indicesLen);
|
||||
return;
|
||||
}
|
||||
|
||||
indicesRef = nullptr;
|
||||
outSize = 0lu;
|
||||
withWeights = _withWeights;
|
||||
|
||||
if (embIndex == _offsetsLen - 1lu)
|
||||
outSize = _indicesLen - offsetsData[embIndex];
|
||||
else
|
||||
outSize = offsetsData[embIndex + 1lu] - offsetsData[embIndex];
|
||||
|
||||
if (outSize != 0lu) {
|
||||
indicesRef = indicesData + offsetsData[embIndex];
|
||||
} else {
|
||||
// Empty or default bag
|
||||
withWeights = false;
|
||||
if (defaultIndex >= 0) {
|
||||
indicesRef = reinterpret_cast<I*>(&defaultIndex);
|
||||
outSize = 1lu;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (withWeights)
|
||||
weightsIdx = offsetsData[embIndex];
|
||||
};
|
||||
|
||||
auto threadBody = [&](const int ithr, const int nthr) {
|
||||
size_t start(0lu), end(0lu);
|
||||
splitter(OUTPUT_BAGS_NUM, nthr, ithr, start, end);
|
||||
if (start >= end)
|
||||
return;
|
||||
|
||||
size_t indicesSize = 0lu;
|
||||
const I* indices = nullptr;
|
||||
size_t weightsIdx = 0lu;
|
||||
bool withWeights = _withWeights;
|
||||
|
||||
for (size_t obi = start; obi < end; obi++) {
|
||||
size_t dstIndex = obi * _embDepth;
|
||||
get_idx(obi, indices, indicesSize, weightsIdx, withWeights);
|
||||
if (indices != nullptr) {
|
||||
withWeights = withWeights & _withWeights;
|
||||
|
||||
size_t inIdx = 0lu;
|
||||
if (indices[inIdx] >= inDataDims[0]) {
|
||||
errorMsg = msgPrefix + "has invalid embedding bag index: " + std::to_string(indices[inIdx]);
|
||||
return;
|
||||
}
|
||||
size_t srcIndex = indices[inIdx] * _embDepth;
|
||||
|
||||
if (withWeights) {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] = srcData[srcIndex + i] * weightsData[weightsIdx];
|
||||
}
|
||||
weightsIdx++;
|
||||
} else {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] = srcData[srcIndex + i];
|
||||
}
|
||||
}
|
||||
|
||||
for (inIdx = 1lu; inIdx < indicesSize; inIdx++) {
|
||||
if (indices[inIdx] >= inDataDims[0]) {
|
||||
errorMsg = msgPrefix + "has invalid embedding bag index: " + std::to_string(indices[inIdx]);
|
||||
return;
|
||||
}
|
||||
size_t srcIndex = indices[inIdx] * _embDepth;
|
||||
|
||||
if (withWeights) {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] += srcData[srcIndex + i] * weightsData[weightsIdx];
|
||||
}
|
||||
weightsIdx++;
|
||||
} else {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] += srcData[srcIndex + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parallel_nt(0, threadBody);
|
||||
|
||||
if (!errorMsg.empty()) {
|
||||
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
void initFromInputs(std::vector<Blob::Ptr>& inputs) override {
|
||||
}
|
||||
|
||||
void getIndices(size_t embIndex, const size_t*& indices, size_t& size, size_t& weightsIdx, bool& withWeights) override {
|
||||
}
|
||||
|
||||
const size_t OFFSETS_IDX = 2lu;
|
||||
|
||||
size_t _indicesLen;
|
||||
size_t _offsetsLen;
|
||||
};
|
||||
|
||||
REG_FACTORY_FOR(EmbeddingBagOffsetsSumImpl, EmbeddingBagOffsetsSum);
|
||||
|
||||
} // namespace Cpu
|
||||
} // namespace Extensions
|
||||
} // namespace InferenceEngine
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "embedding_bag_sum.hpp"
|
||||
|
||||
namespace InferenceEngine {
|
||||
namespace Extensions {
|
||||
namespace Cpu {
|
||||
|
||||
class EmbeddingBagPackedSumImpl: public MKLDNNEmbeddingBagSum {
|
||||
public:
|
||||
explicit EmbeddingBagPackedSumImpl(const CNNLayer* layer) :
|
||||
MKLDNNEmbeddingBagSum(layer, 2lu, 1lu, 2lu, 3lu) {
|
||||
auto indicesData = layer->insData[INDICES_IDX].lock();
|
||||
if (indicesData == nullptr)
|
||||
THROW_IE_EXCEPTION << "'" << layer->name << "' layer has nullable indices data.";
|
||||
if (indicesData->getTensorDesc().getDims().size() != 2)
|
||||
THROW_IE_EXCEPTION << "'" << layer->name << "' layer has indices data with invalid shape.";
|
||||
|
||||
_indices = std::vector<std::vector<size_t>>(
|
||||
indicesData->getTensorDesc().getDims()[0],
|
||||
std::vector<size_t>(indicesData->getTensorDesc().getDims()[1], 0lu));
|
||||
}
|
||||
|
||||
void initFromInputs(std::vector<Blob::Ptr>& inputs) override {
|
||||
// Initialize indices
|
||||
const size_t bagsNum = inputs[INDICES_IDX]->getTensorDesc().getDims()[0];
|
||||
const size_t batch = inputs[INDICES_IDX]->getTensorDesc().getDims()[1];
|
||||
if (inputs[INDICES_IDX]->getTensorDesc().getPrecision().size() == sizeof(INT32)) {
|
||||
const INT32* src = inputs[INDICES_IDX]->cbuffer().as<const INT32*>();
|
||||
for (size_t i = 0lu; i < bagsNum; i++) {
|
||||
size_t ibn = i * batch;
|
||||
for (size_t j = 0lu; j < batch; j++) {
|
||||
_indices[i][j] = static_cast<size_t>(src[ibn + j]);
|
||||
}
|
||||
}
|
||||
} else if (inputs[INDICES_IDX]->getTensorDesc().getPrecision().size() == sizeof(UINT64)) {
|
||||
const UINT64* src = inputs[INDICES_IDX]->cbuffer().as<const UINT64*>();
|
||||
for (size_t i = 0lu; i < bagsNum; i++) {
|
||||
memcpy(_indices[i].data(), src + i * batch, batch * sizeof(UINT64));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getIndices(size_t embIndex, const size_t*& indices, size_t& size, size_t& weightsIdx, bool& withWeights) override {
|
||||
if (embIndex >= _indices.size())
|
||||
THROW_IE_EXCEPTION << "Invalid embedding bag index.";
|
||||
|
||||
withWeights = true;
|
||||
|
||||
indices = _indices[embIndex].data();
|
||||
size = _indices[0].size();
|
||||
|
||||
weightsIdx = embIndex * _indices[0].size();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::vector<std::vector<size_t>> _indices;
|
||||
};
|
||||
|
||||
REG_FACTORY_FOR(EmbeddingBagPackedSumImpl, EmbeddingBagPackedSum);
|
||||
|
||||
} // namespace Cpu
|
||||
} // namespace Extensions
|
||||
} // namespace InferenceEngine
|
||||
@@ -0,0 +1,210 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "embedding_bag_sum.hpp"
|
||||
#include "ie_parallel.hpp"
|
||||
#include "jit_generator.hpp"
|
||||
#include "list.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace InferenceEngine;
|
||||
using namespace InferenceEngine::Extensions::Cpu;
|
||||
|
||||
|
||||
const std::set<size_t> MKLDNNEmbeddingBagSum::_supportedIndicesTypeSize = {sizeof(INT32), sizeof(INT64)};
|
||||
|
||||
MKLDNNEmbeddingBagSum::MKLDNNEmbeddingBagSum(
|
||||
const CNNLayer* layer,
|
||||
size_t requiredInputNum,
|
||||
size_t indicesIdx,
|
||||
size_t perSampleWeightsIdx,
|
||||
size_t defaultIndexIdx,
|
||||
const std::set<Precision>& supportedPrecisions) :
|
||||
INDICES_IDX(indicesIdx),
|
||||
PER_SAMPLE_WEIGHTS_IDX(perSampleWeightsIdx),
|
||||
DEFAULT_INDEX_IDX(defaultIndexIdx) {
|
||||
try {
|
||||
std::string logPrefix = std::string("Layer EmbeddingBagSum with name '") + layer->name + "' ";
|
||||
if (layer->insData.size() < requiredInputNum || layer->outData.size() != 1)
|
||||
THROW_IE_EXCEPTION << logPrefix << "has incorrect number of input or output edges!";
|
||||
_layerName = layer->name;
|
||||
|
||||
auto inData = layer->insData[0].lock();
|
||||
auto indicesData = layer->insData[INDICES_IDX].lock();
|
||||
if (inData == nullptr || indicesData == nullptr)
|
||||
THROW_IE_EXCEPTION << logPrefix << "has nullable input data.";
|
||||
|
||||
auto dataPrecision = inData->getTensorDesc().getPrecision();
|
||||
if (dataPrecision == Precision::BF16)
|
||||
dataPrecision = Precision::FP32;
|
||||
if (!supportedPrecisions.empty()) {
|
||||
if (supportedPrecisions.find(dataPrecision) == supportedPrecisions.end())
|
||||
THROW_IE_EXCEPTION << logPrefix << "has unsupported precision: " << dataPrecision.name();
|
||||
} else {
|
||||
static const std::set<Precision> defaultSupportedPrecisions =
|
||||
{Precision::FP32, Precision::I8, Precision::U8, Precision::I32};
|
||||
if (defaultSupportedPrecisions.find(dataPrecision) == defaultSupportedPrecisions.end())
|
||||
THROW_IE_EXCEPTION << logPrefix << "has unsupported precision: " << dataPrecision.name();
|
||||
}
|
||||
|
||||
if (layer->insData.size() > PER_SAMPLE_WEIGHTS_IDX)
|
||||
_withWeights = true;
|
||||
if (_withWeights) {
|
||||
auto weightsData = layer->insData[PER_SAMPLE_WEIGHTS_IDX].lock();
|
||||
if (weightsData == nullptr)
|
||||
THROW_IE_EXCEPTION << logPrefix << "has nullable weights data";
|
||||
if (weightsData->getTensorDesc().getDims() != indicesData->getTensorDesc().getDims())
|
||||
THROW_IE_EXCEPTION << logPrefix << "must have equal shapes for indices and per_sample_weights inputs.";
|
||||
}
|
||||
|
||||
LayerConfig config;
|
||||
config.inConfs.resize(layer->insData.size());
|
||||
for (int i = 0; i < layer->insData.size(); i++) {
|
||||
auto data = layer->insData[i].lock();
|
||||
if (data == nullptr)
|
||||
THROW_IE_EXCEPTION << logPrefix << "has nullable input data";
|
||||
auto prc = data->getTensorDesc().getPrecision();
|
||||
if (prc == Precision::BF16)
|
||||
prc = Precision::FP32;
|
||||
config.inConfs[i].desc = TensorDesc(prc,
|
||||
data->getTensorDesc().getDims(),
|
||||
TensorDesc::getLayoutByDims(data->getTensorDesc().getDims()));
|
||||
}
|
||||
|
||||
DataConfig outConfig;
|
||||
auto& outDims = layer->outData[0]->getTensorDesc().getDims();
|
||||
outConfig.desc = TensorDesc(dataPrecision,
|
||||
outDims,
|
||||
TensorDesc::getLayoutByDims(outDims));
|
||||
config.outConfs.push_back(outConfig);
|
||||
config.dynBatchSupport = false;
|
||||
|
||||
confs.push_back(config);
|
||||
|
||||
const auto& inDataDims = inData->getTensorDesc().getDims();
|
||||
_embDepth = 1lu;
|
||||
for (size_t i = 1lu; i < inDataDims.size(); i++) {
|
||||
_embDepth *= inDataDims[i];
|
||||
}
|
||||
} catch (InferenceEngine::details::InferenceEngineException &ex) {
|
||||
errorMsg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
StatusCode MKLDNNEmbeddingBagSum::execute(
|
||||
std::vector<Blob::Ptr>& inputs,
|
||||
std::vector<Blob::Ptr>& outputs,
|
||||
ResponseDesc *resp) noexcept {
|
||||
switch (inputs[0]->getTensorDesc().getPrecision()) {
|
||||
case Precision::FP32: {
|
||||
processData<PrecisionTrait<Precision::FP32>::value_type>(inputs, outputs);
|
||||
break;
|
||||
}
|
||||
case Precision::I8: {
|
||||
processData<PrecisionTrait<Precision::I8>::value_type>(inputs, outputs);
|
||||
break;
|
||||
}
|
||||
case Precision::U8: {
|
||||
processData<PrecisionTrait<Precision::U8>::value_type>(inputs, outputs);
|
||||
break;
|
||||
}
|
||||
case Precision::I32: {
|
||||
processData<PrecisionTrait<Precision::I32>::value_type>(inputs, outputs);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (resp) {
|
||||
std::string errorMsg = "EmbeddingBagSum layer does not support precision '"
|
||||
+ std::string(inputs[0]->getTensorDesc().getPrecision().name()) + "'";
|
||||
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
}
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MKLDNNEmbeddingBagSum::processData(
|
||||
std::vector<Blob::Ptr>& inputs,
|
||||
std::vector<Blob::Ptr>& outputs) noexcept {
|
||||
const T* srcData = inputs[0]->cbuffer().as<const T*>() +
|
||||
inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
T* dstData = outputs[0]->buffer().as<T*>() +
|
||||
outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
const T* weightsData = nullptr;
|
||||
if (_withWeights)
|
||||
weightsData = inputs[PER_SAMPLE_WEIGHTS_IDX]->cbuffer().as<const T*>();
|
||||
initFromInputs(inputs);
|
||||
|
||||
const auto& inDataDims = inputs[0]->getTensorDesc().getDims();
|
||||
|
||||
const size_t outputBagsNum = outputs[0]->getTensorDesc().getDims()[0];
|
||||
|
||||
auto threadBody = [&](const int ithr, const int nthr) {
|
||||
size_t start(0lu), end(0lu);
|
||||
splitter(outputBagsNum, nthr, ithr, start, end);
|
||||
if (start >= end)
|
||||
return;
|
||||
|
||||
size_t indicesSize = 0lu;
|
||||
const size_t* indices = nullptr;
|
||||
size_t weightsIdx = 0lu;
|
||||
bool withWeights = _withWeights;
|
||||
|
||||
for (size_t obi = start; obi < end; obi++) {
|
||||
size_t dstIndex = obi * _embDepth;
|
||||
getIndices(obi, indices, indicesSize, weightsIdx, withWeights);
|
||||
|
||||
if (indices != nullptr) {
|
||||
withWeights = withWeights & _withWeights;
|
||||
|
||||
size_t inIdx = 0lu;
|
||||
if (indices[inIdx] >= inDataDims[0])
|
||||
THROW_IE_EXCEPTION << "EmbeddingBagSum layer '" << _layerName
|
||||
<< "' has invalid embedding bag index: " << indices[inIdx];
|
||||
size_t srcIndex = indices[inIdx] * _embDepth;
|
||||
|
||||
if (withWeights) {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] = srcData[srcIndex + i] * weightsData[weightsIdx];
|
||||
}
|
||||
weightsIdx++;
|
||||
} else {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] = srcData[srcIndex + i];
|
||||
}
|
||||
}
|
||||
|
||||
for (inIdx = 1lu; inIdx < indicesSize; inIdx++) {
|
||||
if (indices[inIdx] >= inDataDims[0])
|
||||
THROW_IE_EXCEPTION << "EmbeddingBagSum layer '" << _layerName
|
||||
<< "' has invalid embedding bag index: " << indices[inIdx];
|
||||
size_t srcIndex = indices[inIdx] * _embDepth;
|
||||
|
||||
if (withWeights) {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] += srcData[srcIndex + i] * weightsData[weightsIdx];
|
||||
}
|
||||
weightsIdx++;
|
||||
} else {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] += srcData[srcIndex + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0lu; i < _embDepth; i++) {
|
||||
dstData[dstIndex + i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
parallel_nt(0, threadBody);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace InferenceEngine {
|
||||
namespace Extensions {
|
||||
namespace Cpu {
|
||||
|
||||
class MKLDNNEmbeddingBagSum : public ExtLayerBase {
|
||||
public:
|
||||
MKLDNNEmbeddingBagSum(
|
||||
const CNNLayer* layer,
|
||||
size_t requiredInputsNum,
|
||||
size_t indicesIdx,
|
||||
size_t perSampleWeightsIdx,
|
||||
size_t defaultIndexIdx,
|
||||
const std::set<Precision>& supportedPrecisions = {});
|
||||
|
||||
StatusCode execute(
|
||||
std::vector<Blob::Ptr>& inputs,
|
||||
std::vector<Blob::Ptr>& outputs,
|
||||
ResponseDesc *resp) noexcept override;
|
||||
|
||||
protected:
|
||||
virtual void initFromInputs(std::vector<Blob::Ptr>& inputs) = 0;
|
||||
virtual void getIndices(
|
||||
size_t embIndex,
|
||||
const size_t*& indicesRef,
|
||||
size_t& size,
|
||||
size_t& weightsIdx,
|
||||
bool& withWeights) = 0;
|
||||
|
||||
template<typename T>
|
||||
void processData(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs) noexcept;
|
||||
|
||||
std::set<Precision> _supportedPrecisions;
|
||||
|
||||
const size_t INDICES_IDX;
|
||||
const size_t PER_SAMPLE_WEIGHTS_IDX;
|
||||
const size_t DEFAULT_INDEX_IDX;
|
||||
|
||||
bool _withWeights = false;
|
||||
size_t _embDepth = 0;
|
||||
std::string _layerName;
|
||||
|
||||
using INT32 = PrecisionTrait<Precision::I32>::value_type;
|
||||
using INT64 = PrecisionTrait<Precision::I64>::value_type;
|
||||
using UINT64 = PrecisionTrait<Precision::U64>::value_type;
|
||||
|
||||
static const std::set<size_t> _supportedIndicesTypeSize;
|
||||
};
|
||||
|
||||
} // namespace Cpu
|
||||
} // namespace Extensions
|
||||
} // namespace InferenceEngine
|
||||
@@ -0,0 +1,133 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "embedding_bag_sum.hpp"
|
||||
|
||||
namespace InferenceEngine {
|
||||
namespace Extensions {
|
||||
namespace Cpu {
|
||||
|
||||
class EmbeddingSegmentsSumImpl: public MKLDNNEmbeddingBagSum {
|
||||
public:
|
||||
explicit EmbeddingSegmentsSumImpl(const CNNLayer* layer) :
|
||||
MKLDNNEmbeddingBagSum(layer, 4lu, 1lu, 5lu, 4lu) {
|
||||
std::string errPrefix = std::string("EmbeddingSegmentsSum layer with name '") + _layerName + "' ";
|
||||
auto indicesData = layer->insData[INDICES_IDX].lock();
|
||||
if (indicesData == nullptr)
|
||||
THROW_IE_EXCEPTION << errPrefix << "has nullable indices data.";
|
||||
if (indicesData->getTensorDesc().getDims().size() != 1)
|
||||
THROW_IE_EXCEPTION << errPrefix << "has indices data with invalid shape: "
|
||||
<< indicesData->getTensorDesc().getDims().size();
|
||||
|
||||
auto segmentIdData = layer->insData[SEGMENT_ID_IDX].lock();
|
||||
if (segmentIdData == nullptr)
|
||||
THROW_IE_EXCEPTION << errPrefix << "has invalid segmentID data.";
|
||||
if (segmentIdData->getTensorDesc().getDims().size() != 1)
|
||||
THROW_IE_EXCEPTION << errPrefix << "has invalid segmentID data shape: "
|
||||
<< segmentIdData->getTensorDesc().getDims().size();
|
||||
|
||||
auto numSegmentData = layer->insData[NUM_SEGMENTS_IDX].lock();
|
||||
if (numSegmentData == nullptr)
|
||||
THROW_IE_EXCEPTION << errPrefix << "has nullable numSegmentID data.";
|
||||
|
||||
if (_supportedIndicesTypeSize.find(indicesData->getTensorDesc().getPrecision().size())
|
||||
== _supportedIndicesTypeSize.end()
|
||||
|| _supportedIndicesTypeSize.find(segmentIdData->getTensorDesc().getPrecision().size())
|
||||
== _supportedIndicesTypeSize.end()
|
||||
|| _supportedIndicesTypeSize.find(numSegmentData->getTensorDesc().getPrecision().size())
|
||||
== _supportedIndicesTypeSize.end())
|
||||
THROW_IE_EXCEPTION << errPrefix << "has unsupported input data type.";
|
||||
|
||||
_indices = std::vector<size_t>(indicesData->getTensorDesc().getDims()[0], 0lu);
|
||||
_segmentIds = std::vector<size_t>(segmentIdData->getTensorDesc().getDims()[0], 0lu);
|
||||
}
|
||||
|
||||
void initFromInputs(std::vector<Blob::Ptr>& inputs) override {
|
||||
// Initialize indices
|
||||
if (inputs[INDICES_IDX]->getTensorDesc().getPrecision().size() == sizeof(INT32)) {
|
||||
const INT32* src = inputs[INDICES_IDX]->cbuffer().as<const INT32*>();
|
||||
for (size_t i = 0lu; i < inputs[INDICES_IDX]->size(); i++)
|
||||
_indices[i] = static_cast<size_t>(src[i]);
|
||||
} else if (inputs[INDICES_IDX]->getTensorDesc().getPrecision().size() == sizeof(UINT64)) {
|
||||
const UINT64* src = inputs[INDICES_IDX]->cbuffer().as<const UINT64*>();
|
||||
memcpy(_indices.data(), src, inputs[INDICES_IDX]->byteSize());
|
||||
}
|
||||
|
||||
// Initialize segments ids
|
||||
if (inputs[SEGMENT_ID_IDX]->getTensorDesc().getPrecision().size() == sizeof(INT32)) {
|
||||
const INT32* src = inputs[SEGMENT_ID_IDX]->cbuffer().as<const INT32*>();
|
||||
for (size_t i = 0lu; i < inputs[SEGMENT_ID_IDX]->size(); i++)
|
||||
_segmentIds[i] = static_cast<size_t>(src[i]);
|
||||
} else if (inputs[SEGMENT_ID_IDX]->getTensorDesc().getPrecision().size() == sizeof(UINT64)) {
|
||||
const UINT64* src = inputs[SEGMENT_ID_IDX]->cbuffer().as<const UINT64*>();
|
||||
memcpy(_segmentIds.data(), src, inputs[SEGMENT_ID_IDX]->byteSize());
|
||||
}
|
||||
|
||||
if (inputs.size() > NUM_SEGMENTS_IDX) {
|
||||
if (inputs[NUM_SEGMENTS_IDX]->getTensorDesc().getPrecision().size() == sizeof(INT32)) {
|
||||
const INT32* src = inputs[NUM_SEGMENTS_IDX]->cbuffer().as<const INT32*>();
|
||||
_numSegments = static_cast<size_t>(*src);
|
||||
} else if (inputs[NUM_SEGMENTS_IDX]->getTensorDesc().getPrecision().size() == sizeof(UINT64)) {
|
||||
const INT64* src = inputs[NUM_SEGMENTS_IDX]->cbuffer().as<const INT64*>();
|
||||
_numSegments = *src;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize default index
|
||||
_defaultIndices.clear();
|
||||
if (inputs.size() > DEFAULT_INDEX_IDX) {
|
||||
if (inputs[DEFAULT_INDEX_IDX]->getTensorDesc().getPrecision().size() == sizeof(INT32)) {
|
||||
const INT32* src = inputs[DEFAULT_INDEX_IDX]->cbuffer().as<const INT32*>();
|
||||
_defaultIndices.push_back(static_cast<size_t>(*src));
|
||||
} else if (inputs[DEFAULT_INDEX_IDX]->getTensorDesc().getPrecision().size() == sizeof(UINT64)) {
|
||||
const INT64* src = inputs[DEFAULT_INDEX_IDX]->cbuffer().as<const INT64*>();
|
||||
_defaultIndices.push_back(*src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getIndices(size_t embIndex, const size_t*& indices, size_t& size, size_t& weightsIdx, bool& withWeight) override {
|
||||
if (embIndex >= _numSegments)
|
||||
THROW_IE_EXCEPTION << "Invalid embedding bag index.";
|
||||
|
||||
indices = nullptr;
|
||||
size = 0lu;
|
||||
withWeight = true;
|
||||
|
||||
for (size_t si = 0; si < _indices.size(); si++) {
|
||||
if (_segmentIds[si] == embIndex) {
|
||||
size++;
|
||||
if (indices == nullptr) {
|
||||
indices = _indices.data() + si;
|
||||
weightsIdx = si;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Empty bag
|
||||
if (size == 0) {
|
||||
size = 1lu;
|
||||
withWeight = false;
|
||||
if (_defaultIndices.size() == 1lu)
|
||||
indices = _defaultIndices.data();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
const size_t SEGMENT_ID_IDX = 2lu;
|
||||
const size_t NUM_SEGMENTS_IDX = 3lu;
|
||||
|
||||
size_t _numSegments = 0lu;
|
||||
|
||||
std::vector<size_t> _indices;
|
||||
std::vector<size_t> _segmentIds;
|
||||
std::vector<size_t> _defaultIndices;
|
||||
};
|
||||
|
||||
REG_FACTORY_FOR(EmbeddingSegmentsSumImpl, EmbeddingSegmentsSum);
|
||||
|
||||
} // namespace Cpu
|
||||
} // namespace Extensions
|
||||
} // namespace InferenceEngine
|
||||
@@ -7,6 +7,9 @@
|
||||
# define MKLDNN_EXTENSION_NODE(__prim, __type)
|
||||
#endif
|
||||
|
||||
MKLDNN_EXTENSION_NODE(EmbeddingBagOffsetsSumImpl, EmbeddingBagOffsetsSum);
|
||||
MKLDNN_EXTENSION_NODE(EmbeddingBagPackedSumImpl, EmbeddingBagPackedSum);
|
||||
MKLDNN_EXTENSION_NODE(EmbeddingSegmentsSumImpl, EmbeddingSegmentsSum);
|
||||
MKLDNN_EXTENSION_NODE(PriorBoxImpl, PriorBox);
|
||||
MKLDNN_EXTENSION_NODE(MathImpl, Abs);
|
||||
MKLDNN_EXTENSION_NODE(MathImpl, Acos);
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "single_layer_tests/embedding_bag_offsets_sum.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<InferenceEngine::Precision> netPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::I32,
|
||||
InferenceEngine::Precision::U8
|
||||
};
|
||||
|
||||
const std::vector<InferenceEngine::Precision> indPrecisions = {
|
||||
InferenceEngine::Precision::I64,
|
||||
InferenceEngine::Precision::I32
|
||||
};
|
||||
|
||||
const std::vector<std::vector<size_t>> emb_table_shape = {{5, 6}, {10, 35}, {5, 4, 16}};
|
||||
const std::vector<std::vector<size_t>> indices =
|
||||
{{0, 1, 2, 2, 3}, {4, 4, 3, 1, 0}, {1, 2, 1, 2, 1, 2, 1, 2, 1, 2}};
|
||||
const std::vector<std::vector<size_t>> offsets = {{0, 2}, {0, 0, 2, 2}, {2, 4}};
|
||||
const std::vector<size_t> default_index = {0, 4};
|
||||
const std::vector<bool> with_weights = {false, true};
|
||||
const std::vector<bool> with_default_index = {false, true};
|
||||
|
||||
const auto embBagOffsetSumArgSet = ::testing::Combine(
|
||||
::testing::ValuesIn(emb_table_shape),
|
||||
::testing::ValuesIn(indices),
|
||||
::testing::ValuesIn(offsets),
|
||||
::testing::ValuesIn(default_index),
|
||||
::testing::ValuesIn(with_weights),
|
||||
::testing::ValuesIn(with_default_index)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(smoke, EmbeddingBagOffsetsSumLayerTest,
|
||||
::testing::Combine(
|
||||
embBagOffsetSumArgSet,
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::ValuesIn(indPrecisions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)),
|
||||
EmbeddingBagOffsetsSumLayerTest::getTestCaseName);
|
||||
} // namespace
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "single_layer_tests/embedding_bag_packed_sum.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<InferenceEngine::Precision> netPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::I32,
|
||||
InferenceEngine::Precision::U8
|
||||
};
|
||||
|
||||
const std::vector<InferenceEngine::Precision> indPrecisions = {
|
||||
InferenceEngine::Precision::I64,
|
||||
InferenceEngine::Precision::I32
|
||||
};
|
||||
|
||||
const std::vector<std::vector<size_t>> emb_table_shape = {{5, 6}, {10, 35}, {5, 4, 16}};
|
||||
const std::vector<std::vector<std::vector<size_t>>> indices =
|
||||
{{{0, 1}, {2, 2}, {3, 4}}, {{4, 4, 3}, {1, 0, 2}}, {{1, 2, 1, 2}, {1, 2, 1, 2}}};
|
||||
const std::vector<bool> with_weights = {false, true};
|
||||
|
||||
const auto embBagPackedSumArgSet = ::testing::Combine(
|
||||
::testing::ValuesIn(emb_table_shape),
|
||||
::testing::ValuesIn(indices),
|
||||
::testing::ValuesIn(with_weights)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(smoke, EmbeddingBagPackedSumLayerTest,
|
||||
::testing::Combine(
|
||||
embBagPackedSumArgSet,
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::ValuesIn(indPrecisions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)),
|
||||
EmbeddingBagPackedSumLayerTest::getTestCaseName);
|
||||
} // namespace
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "single_layer_tests/embedding_segments_sum.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
|
||||
const std::vector<InferenceEngine::Precision> netPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::I32,
|
||||
InferenceEngine::Precision::U8
|
||||
};
|
||||
|
||||
const std::vector<InferenceEngine::Precision> indPrecisions = {
|
||||
InferenceEngine::Precision::I64,
|
||||
InferenceEngine::Precision::I32
|
||||
};
|
||||
|
||||
const std::vector<std::vector<size_t>> emb_table_shape = {{5, 6}, {10, 35}, {5, 4, 16}};
|
||||
const std::vector<std::vector<size_t>> indices =
|
||||
{{0, 1, 2, 2, 3}, {4, 4, 3, 1, 2}};
|
||||
const std::vector<std::vector<size_t>> segment_ids = {{0, 1, 2, 3, 4}, {0, 0, 2, 2, 4}};
|
||||
const std::vector<size_t> num_segments = {5, 7};
|
||||
const std::vector<size_t> default_index = {0, 4};
|
||||
const std::vector<bool> with_weights = {false, true};
|
||||
const std::vector<bool> with_default_index = {false, true};
|
||||
|
||||
const auto embSegmentsSumArgSet = ::testing::Combine(
|
||||
::testing::ValuesIn(emb_table_shape),
|
||||
::testing::ValuesIn(indices),
|
||||
::testing::ValuesIn(segment_ids),
|
||||
::testing::ValuesIn(num_segments),
|
||||
::testing::ValuesIn(default_index),
|
||||
::testing::ValuesIn(with_weights),
|
||||
::testing::ValuesIn(with_default_index)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(smoke, EmbeddingSegmentsSumLayerTest,
|
||||
::testing::Combine(
|
||||
embSegmentsSumArgSet,
|
||||
::testing::ValuesIn(netPrecisions),
|
||||
::testing::ValuesIn(indPrecisions),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)),
|
||||
EmbeddingSegmentsSumLayerTest::getTestCaseName);
|
||||
} // namespace
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
|
||||
typedef std::tuple<
|
||||
std::vector<size_t>, // emb_table_shape
|
||||
std::vector<size_t>, // indices
|
||||
std::vector<size_t>, // offsets
|
||||
size_t, // default_index
|
||||
bool, // with_weights
|
||||
bool // with_def_index
|
||||
> embeddingBagOffsetsSumParams;
|
||||
|
||||
typedef std::tuple<
|
||||
embeddingBagOffsetsSumParams,
|
||||
InferenceEngine::Precision, // embedding table
|
||||
InferenceEngine::Precision, // indices
|
||||
LayerTestsUtils::TargetDevice> embeddingBagOffsetsSumLayerTestParamsSet;
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
class EmbeddingBagOffsetsSumLayerTest : public testing::WithParamInterface<embeddingBagOffsetsSumLayerTestParamsSet>,
|
||||
public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<embeddingBagOffsetsSumLayerTestParamsSet> obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
|
||||
typedef std::tuple<
|
||||
std::vector<size_t>, // emb_table_shape
|
||||
std::vector<std::vector<size_t>>, // indices
|
||||
bool // with_weights
|
||||
> embeddingBagPackedSumParams;
|
||||
|
||||
typedef std::tuple<
|
||||
embeddingBagPackedSumParams,
|
||||
InferenceEngine::Precision, // embedding table
|
||||
InferenceEngine::Precision, // indices
|
||||
LayerTestsUtils::TargetDevice> embeddingBagPackedSumLayerTestParamsSet;
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
class EmbeddingBagPackedSumLayerTest : public testing::WithParamInterface<embeddingBagPackedSumLayerTestParamsSet>,
|
||||
public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<embeddingBagPackedSumLayerTestParamsSet> obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
|
||||
typedef std::tuple<
|
||||
std::vector<size_t>, // emb_table_shape
|
||||
std::vector<size_t>, // indices
|
||||
std::vector<size_t>, // segment_ids
|
||||
size_t, // num_segments
|
||||
size_t, // default_index
|
||||
bool, // with_weights
|
||||
bool // with_def_index
|
||||
> embeddingSegmentsSumParams;
|
||||
|
||||
typedef std::tuple<
|
||||
embeddingSegmentsSumParams,
|
||||
InferenceEngine::Precision, // embedding table
|
||||
InferenceEngine::Precision, // indices
|
||||
LayerTestsUtils::TargetDevice> embeddingSegmentsSumLayerTestParamsSet;
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
class EmbeddingSegmentsSumLayerTest : public testing::WithParamInterface<embeddingSegmentsSumLayerTestParamsSet>,
|
||||
public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(testing::TestParamInfo<embeddingSegmentsSumLayerTestParamsSet> obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "single_layer_tests/embedding_bag_offsets_sum.hpp"
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
std::string EmbeddingBagOffsetsSumLayerTest::getTestCaseName(testing::TestParamInfo<embeddingBagOffsetsSumLayerTestParamsSet> obj) {
|
||||
embeddingBagOffsetsSumParams params;
|
||||
InferenceEngine::Precision netPrecision, indPrecision;
|
||||
std::string targetDevice;
|
||||
std::tie(params, netPrecision, indPrecision, targetDevice) = obj.param;
|
||||
std::vector<size_t> embTableShape, indices, offsets;
|
||||
size_t defaultIndex;
|
||||
bool withWeights, withDefIndex;
|
||||
std::tie(embTableShape, indices, offsets, defaultIndex, withWeights, withDefIndex) = params;
|
||||
|
||||
std::ostringstream result;
|
||||
result << "ETS=" << CommonTestUtils::vec2str(embTableShape) << "_";
|
||||
result << "I" << CommonTestUtils::vec2str(indices) << "_";
|
||||
result << "O" << CommonTestUtils::vec2str(offsets) << "_";
|
||||
result << "DI" << defaultIndex << "_";
|
||||
result << "WW" << withWeights << "_";
|
||||
result << "WDI" << withDefIndex << "_";
|
||||
result << "netPRC=" << netPrecision.name() << "_";
|
||||
result << "indPRC=" << indPrecision.name() << "_";
|
||||
result << "targetDevice=" << targetDevice;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void EmbeddingBagOffsetsSumLayerTest::SetUp() {
|
||||
embeddingBagOffsetsSumParams embParams;
|
||||
auto netPrecision = InferenceEngine::Precision::UNSPECIFIED;
|
||||
auto indPrecision = netPrecision;
|
||||
std::tie(embParams, netPrecision, indPrecision, targetDevice) = this->GetParam();
|
||||
std::vector<size_t> embTableShape, indices, offsets;
|
||||
bool withWeights, withDefIndex;
|
||||
size_t defaultIndex;
|
||||
std::tie(embTableShape, indices, offsets, defaultIndex, withWeights, withDefIndex) = embParams;
|
||||
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
|
||||
auto ngIdxPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(indPrecision);
|
||||
|
||||
auto emb_table_node = std::make_shared<ngraph::opset1::Parameter>(ngPrc, ngraph::Shape(embTableShape));
|
||||
ngraph::ParameterVector params = {emb_table_node};
|
||||
|
||||
auto embBag = std::dynamic_pointer_cast<ngraph::opset3::EmbeddingBagOffsetsSum>(
|
||||
ngraph::builder::makeEmbeddingBagOffsetsSum(
|
||||
ngPrc, ngIdxPrc, emb_table_node, indices, offsets, defaultIndex, withWeights, withDefIndex));
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(embBag)};
|
||||
function = std::make_shared<ngraph::Function>(results, params, "embeddingBagOffsetsSum");
|
||||
}
|
||||
|
||||
TEST_P(EmbeddingBagOffsetsSumLayerTest, CompareWithRefs) {
|
||||
Run();
|
||||
}
|
||||
} // namespace LayerTestsDefinitions
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "single_layer_tests/embedding_bag_packed_sum.hpp"
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
std::string EmbeddingBagPackedSumLayerTest::getTestCaseName(testing::TestParamInfo<embeddingBagPackedSumLayerTestParamsSet> obj) {
|
||||
embeddingBagPackedSumParams params;
|
||||
InferenceEngine::Precision netPrecision, indPrecision;
|
||||
std::string targetDevice;
|
||||
std::tie(params, netPrecision, indPrecision, targetDevice) = obj.param;
|
||||
std::vector<size_t> embTableShape;
|
||||
std::vector<std::vector<size_t>> indices;
|
||||
bool withWeights;
|
||||
std::tie(embTableShape, indices, withWeights) = params;
|
||||
|
||||
std::ostringstream result;
|
||||
result << "ETS=" << CommonTestUtils::vec2str(embTableShape) << "_";
|
||||
result << "I" << CommonTestUtils::vec2str(indices) << "_";
|
||||
result << "WW" << withWeights << "_";
|
||||
result << "netPRC=" << netPrecision.name() << "_";
|
||||
result << "indPRC=" << indPrecision.name() << "_";
|
||||
result << "targetDevice=" << targetDevice;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void EmbeddingBagPackedSumLayerTest::SetUp() {
|
||||
embeddingBagPackedSumParams embParams;
|
||||
auto netPrecision = InferenceEngine::Precision::UNSPECIFIED;
|
||||
auto indPrecision = netPrecision;
|
||||
std::tie(embParams, netPrecision, indPrecision, targetDevice) = this->GetParam();
|
||||
std::vector<size_t> embTableShape;
|
||||
std::vector<std::vector<size_t>> indices;
|
||||
bool withWeights;
|
||||
std::tie(embTableShape, indices, withWeights) = embParams;
|
||||
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
|
||||
auto ngIdxPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(indPrecision);
|
||||
|
||||
auto emb_table_node = std::make_shared<ngraph::opset1::Parameter>(ngPrc, ngraph::Shape(embTableShape));
|
||||
ngraph::ParameterVector params = {emb_table_node};
|
||||
|
||||
auto embBag = std::dynamic_pointer_cast<ngraph::opset3::EmbeddingBagPackedSum>(
|
||||
ngraph::builder::makeEmbeddingBagPackedSum(
|
||||
ngPrc, ngIdxPrc, emb_table_node, indices, withWeights));
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(embBag)};
|
||||
function = std::make_shared<ngraph::Function>(results, params, "embeddingBagPackedSum");
|
||||
}
|
||||
|
||||
TEST_P(EmbeddingBagPackedSumLayerTest, CompareWithRefs) {
|
||||
Run();
|
||||
}
|
||||
} // namespace LayerTestsDefinitions
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include "single_layer_tests/embedding_segments_sum.hpp"
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
std::string EmbeddingSegmentsSumLayerTest::getTestCaseName(testing::TestParamInfo<embeddingSegmentsSumLayerTestParamsSet> obj) {
|
||||
embeddingSegmentsSumParams params;
|
||||
InferenceEngine::Precision netPrecision, indPrecision;
|
||||
std::string targetDevice;
|
||||
std::tie(params, netPrecision, indPrecision, targetDevice) = obj.param;
|
||||
std::vector<size_t> embTableShape, indices, segmentIds;
|
||||
size_t numSegments, defaultIndex;
|
||||
bool withWeights, withDefIndex;
|
||||
std::tie(embTableShape, indices, segmentIds, numSegments, defaultIndex, withWeights, withDefIndex) = params;
|
||||
|
||||
std::ostringstream result;
|
||||
result << "ETS=" << CommonTestUtils::vec2str(embTableShape) << "_";
|
||||
result << "I" << CommonTestUtils::vec2str(indices) << "_";
|
||||
result << "SI" << CommonTestUtils::vec2str(segmentIds) << "_";
|
||||
result << "NS" << numSegments << "_";
|
||||
result << "DI" << defaultIndex << "_";
|
||||
result << "WW" << withWeights << "_";
|
||||
result << "WDI" << withDefIndex << "_";
|
||||
result << "netPRC=" << netPrecision.name() << "_";
|
||||
result << "indPRC=" << indPrecision.name() << "_";
|
||||
result << "targetDevice=" << targetDevice;
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void EmbeddingSegmentsSumLayerTest::SetUp() {
|
||||
embeddingSegmentsSumParams embParams;
|
||||
auto netPrecision = InferenceEngine::Precision::UNSPECIFIED;
|
||||
auto indPrecision = netPrecision;
|
||||
std::tie(embParams, netPrecision, indPrecision, targetDevice) = this->GetParam();
|
||||
std::vector<size_t> embTableShape, indices, segmentIds;
|
||||
bool withWeights, withDefIndex;
|
||||
size_t numSegments, defaultIndex;
|
||||
std::tie(embTableShape, indices, segmentIds, numSegments, defaultIndex, withWeights, withDefIndex) = embParams;
|
||||
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
|
||||
auto ngIdxPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(indPrecision);
|
||||
|
||||
auto emb_table_node = std::make_shared<ngraph::opset1::Parameter>(ngPrc, ngraph::Shape(embTableShape));
|
||||
ngraph::ParameterVector params = {emb_table_node};
|
||||
|
||||
auto embBag = std::dynamic_pointer_cast<ngraph::opset3::EmbeddingSegmentsSum>(
|
||||
ngraph::builder::makeEmbeddingSegmentsSum(
|
||||
ngPrc, ngIdxPrc, emb_table_node, indices, segmentIds, numSegments, defaultIndex, withWeights, withDefIndex));
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(embBag)};
|
||||
function = std::make_shared<ngraph::Function>(results, params, "embeddingSegmentsSum");
|
||||
}
|
||||
|
||||
TEST_P(EmbeddingSegmentsSumLayerTest, CompareWithRefs) {
|
||||
Run();
|
||||
}
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
||||
@@ -184,5 +184,34 @@ std::shared_ptr<ngraph::Node> makeCumSum(const ngraph::Output<Node> &in,
|
||||
bool exclusive,
|
||||
bool reverse);
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeEmbeddingBagOffsetsSum(
|
||||
const element::Type& dataType,
|
||||
const element::Type& indicesType,
|
||||
const ngraph::Output<Node>& emb_table_node,
|
||||
const std::vector<size_t>& indices,
|
||||
const std::vector<size_t>& offsets,
|
||||
size_t default_index,
|
||||
bool with_weights,
|
||||
bool with_default_index);
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeEmbeddingBagPackedSum(
|
||||
const element::Type& dataType,
|
||||
const element::Type& indicesType,
|
||||
const ngraph::Output<Node>& emb_table_node,
|
||||
const std::vector<std::vector<size_t>>& indices,
|
||||
bool with_weights);
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeEmbeddingSegmentsSum(
|
||||
const element::Type& dataType,
|
||||
const element::Type& indicesType,
|
||||
const ngraph::Output<Node>& emb_table_node,
|
||||
const std::vector<size_t>& indices,
|
||||
const std::vector<size_t>& segment_ids,
|
||||
size_t num_segments,
|
||||
size_t default_index,
|
||||
bool with_weights,
|
||||
bool with_default_index);
|
||||
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
|
||||
std::shared_ptr<Node> makeEmbeddingBagOffsetsSum(
|
||||
const element::Type& dataType,
|
||||
const element::Type& indicesType,
|
||||
const ngraph::Output<Node>& embTableNode,
|
||||
const std::vector<size_t>& indices,
|
||||
const std::vector<size_t>& offsets,
|
||||
size_t default_index,
|
||||
bool with_weights,
|
||||
bool with_default_index) {
|
||||
std::vector<size_t> i_shape = {indices.size()};
|
||||
auto indicesNode = std::make_shared<ngraph::opset1::Constant>(indicesType, i_shape, indices);
|
||||
std::vector<size_t> o_shape = {offsets.size()};
|
||||
auto offsetsNode = std::make_shared<ngraph::opset1::Constant>(indicesType, o_shape, offsets);
|
||||
|
||||
std::shared_ptr<Node> embBag;
|
||||
if (with_default_index) {
|
||||
std::vector<size_t> d_shape = {};
|
||||
auto defIdxNode = std::make_shared<ngraph::opset1::Constant>(indicesType, d_shape, default_index);
|
||||
if (with_weights) {
|
||||
auto weightsNode = makeConstant(dataType, {indices.size()}, {}, true);
|
||||
|
||||
embBag = std::make_shared<opset3::EmbeddingBagOffsetsSum>(
|
||||
embTableNode, indicesNode, offsetsNode, defIdxNode, weightsNode);
|
||||
} else {
|
||||
embBag = std::make_shared<opset3::EmbeddingBagOffsetsSum>(
|
||||
embTableNode, indicesNode, offsetsNode, defIdxNode);
|
||||
}
|
||||
} else {
|
||||
embBag = std::make_shared<opset3::EmbeddingBagOffsetsSum>(
|
||||
embTableNode, indicesNode, offsetsNode);
|
||||
}
|
||||
return embBag;
|
||||
}
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
|
||||
std::shared_ptr<Node> makeEmbeddingBagPackedSum(
|
||||
const element::Type& dataType,
|
||||
const element::Type& indicesType,
|
||||
const ngraph::Output<Node>& embTableNode,
|
||||
const std::vector<std::vector<size_t>>& indices,
|
||||
bool with_weights) {
|
||||
std::vector<size_t> i_shape({indices.size(), indices[0].size()});
|
||||
size_t i_size = ngraph::shape_size(i_shape);
|
||||
std::vector<size_t> i_values(i_size);
|
||||
for (int i = 0; i < indices.size(); i++)
|
||||
memcpy(i_values.data() + indices[0].size() * i, indices[i].data(), indices[0].size() * sizeof(size_t));
|
||||
auto indicesNode = std::make_shared<ngraph::opset1::Constant>(indicesType, i_shape, i_values);
|
||||
|
||||
std::shared_ptr<Node> embBag;
|
||||
if (with_weights) {
|
||||
auto weightsNode = makeConstant(dataType, i_shape, {}, true);
|
||||
|
||||
embBag = std::make_shared<opset3::EmbeddingBagPackedSum>(
|
||||
embTableNode, indicesNode, weightsNode);
|
||||
} else {
|
||||
embBag = std::make_shared<opset3::EmbeddingBagPackedSum>(
|
||||
embTableNode, indicesNode);
|
||||
}
|
||||
return embBag;
|
||||
}
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
|
||||
std::shared_ptr<Node> makeEmbeddingSegmentsSum(
|
||||
const element::Type& dataType,
|
||||
const element::Type& indicesType,
|
||||
const ngraph::Output<Node>& embTableNode,
|
||||
const std::vector<size_t>& indices,
|
||||
const std::vector<size_t>& segment_ids,
|
||||
size_t num_segments,
|
||||
size_t default_index,
|
||||
bool with_weights,
|
||||
bool with_default_index) {
|
||||
std::vector<size_t> i_shape = {indices.size()};
|
||||
auto indicesNode = std::make_shared<ngraph::opset1::Constant>(indicesType, i_shape, indices);
|
||||
std::vector<size_t> o_shape = {segment_ids.size()};
|
||||
auto segmentIdNode = std::make_shared<ngraph::opset1::Constant>(indicesType, o_shape, segment_ids);
|
||||
std::vector<size_t> shape_0 = {};
|
||||
auto segmentNumNode = std::make_shared<ngraph::opset1::Constant>(indicesType, shape_0, num_segments);
|
||||
|
||||
std::shared_ptr<Node> embBag;
|
||||
if (with_default_index) {
|
||||
auto defIdxNode = std::make_shared<ngraph::opset1::Constant>(indicesType, shape_0, default_index);
|
||||
if (with_weights) {
|
||||
auto weightsNode = makeConstant(dataType, {indices.size()}, {}, true);
|
||||
|
||||
embBag = std::make_shared<opset3::EmbeddingSegmentsSum>(
|
||||
embTableNode, indicesNode, segmentIdNode, segmentNumNode, defIdxNode, weightsNode);
|
||||
} else {
|
||||
embBag = std::make_shared<opset3::EmbeddingSegmentsSum>(
|
||||
embTableNode, indicesNode, segmentIdNode, segmentNumNode, defIdxNode);
|
||||
}
|
||||
} else {
|
||||
embBag = std::make_shared<opset3::EmbeddingSegmentsSum>(
|
||||
embTableNode, indicesNode, segmentIdNode, segmentNumNode);
|
||||
}
|
||||
return embBag;
|
||||
}
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
@@ -0,0 +1,98 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/shape_util.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace runtime {
|
||||
namespace reference {
|
||||
template <typename T, typename U>
|
||||
void embeddingBagOffsetsSum(
|
||||
const T* emb_table,
|
||||
const U* indices,
|
||||
const U* offsets,
|
||||
const U* default_index,
|
||||
const T* weights,
|
||||
T* out,
|
||||
const size_t indices_count,
|
||||
const Shape& outShape) {
|
||||
const size_t offsets_size = outShape[0];
|
||||
std::vector<U> default_indices;
|
||||
if (default_index)
|
||||
default_indices.push_back(default_index[0]);
|
||||
|
||||
size_t embDepth = 1;
|
||||
for (size_t i = 1; i < outShape.size(); i++) {
|
||||
embDepth *= outShape[i];
|
||||
}
|
||||
memset(out, 0, shape_size(outShape) * sizeof(T));
|
||||
|
||||
auto get_indices = [&](size_t emb_index, const U*& indices_ref, size_t& indices_num, size_t& weights_idx, bool& with_weights) {
|
||||
if (emb_index >= offsets_size)
|
||||
throw ngraph_error("Invalid embedding bag index.");
|
||||
if (offsets[emb_index] >= indices_count)
|
||||
throw ngraph_error(std::string("Offset value exceeds indices size in the model.\noffset: ")
|
||||
+ std::to_string(offsets[emb_index]) + "; indices size: "
|
||||
+ std::to_string(indices_count));
|
||||
|
||||
indices_ref = nullptr;
|
||||
indices_num = 0lu;
|
||||
with_weights = (weights != nullptr);
|
||||
|
||||
if (emb_index == offsets_size - 1lu)
|
||||
indices_num = indices_count - offsets[emb_index];
|
||||
else
|
||||
indices_num = offsets[emb_index + 1lu] - offsets[emb_index];
|
||||
|
||||
if (indices_num != 0lu) {
|
||||
indices_ref = indices + offsets[emb_index];
|
||||
} else {
|
||||
// Empty or default bag
|
||||
with_weights = false;
|
||||
if (default_indices.size() == 1lu) {
|
||||
indices_ref = default_indices.data();
|
||||
indices_num = 1lu;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (with_weights)
|
||||
weights_idx = offsets[emb_index];
|
||||
};
|
||||
|
||||
size_t indices_size = 0lu;
|
||||
const U* indices_emb = nullptr;
|
||||
size_t weights_idx = 0lu;
|
||||
bool with_weights_b = (weights != nullptr);
|
||||
bool with_weights = with_weights_b;
|
||||
|
||||
for (size_t obi = 0lu; obi < outShape.at(0); obi++) {
|
||||
size_t dst_index = obi * embDepth;
|
||||
get_indices(obi, indices_emb, indices_size, weights_idx, with_weights);
|
||||
if (indices_emb != nullptr) {
|
||||
with_weights = with_weights_b & with_weights;
|
||||
for (size_t in_idx = 0lu; in_idx < indices_size; in_idx++) {
|
||||
size_t src_index = indices_emb[in_idx] * embDepth;
|
||||
|
||||
if (with_weights) {
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] += emb_table[src_index + i] * weights[weights_idx];
|
||||
}
|
||||
weights_idx++;
|
||||
} else {
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] += emb_table[src_index + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // embeddingBagOffsetsSum
|
||||
|
||||
} // reference
|
||||
} // runtime
|
||||
} // ngraph
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/shape_util.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace runtime {
|
||||
namespace reference {
|
||||
template <typename T, typename U>
|
||||
void embeddingBagPackedSum(
|
||||
const T* emb_table,
|
||||
const U* indices,
|
||||
const T* weights,
|
||||
T* out,
|
||||
const Shape& indicesShape,
|
||||
const Shape& outShape) {
|
||||
const size_t indices_per_bag = indicesShape[1];
|
||||
|
||||
size_t embDepth = 1lu;
|
||||
for (size_t i = 1; i < outShape.size(); i++) {
|
||||
embDepth *= outShape[i];
|
||||
}
|
||||
memset(out, 0, shape_size(outShape) * sizeof(T));
|
||||
|
||||
bool with_weights = (weights != nullptr);
|
||||
size_t idx_idx = 0lu;
|
||||
|
||||
for (size_t obi = 0lu; obi < outShape.at(0); obi++) {
|
||||
size_t dst_index = obi * embDepth;
|
||||
for (size_t in_idx = 0lu; in_idx < indices_per_bag; in_idx++, idx_idx++) {
|
||||
size_t src_index = indices[idx_idx] * embDepth;
|
||||
|
||||
if (with_weights) {
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] += emb_table[src_index + i] * weights[idx_idx];
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] += emb_table[src_index + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // embeddingBagPackedSum
|
||||
|
||||
} // reference
|
||||
} // runtime
|
||||
} // ngraph
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/shape_util.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace runtime {
|
||||
namespace reference {
|
||||
|
||||
template <typename T, typename U>
|
||||
void embeddingSegmentsSum(
|
||||
const T* embTable,
|
||||
const U* indices,
|
||||
const U* segmentIds,
|
||||
const U* defaultIndex,
|
||||
const T* weights,
|
||||
T* out,
|
||||
const Shape& embTableShape,
|
||||
const Shape& indicesShape,
|
||||
const Shape& outShape) {
|
||||
const size_t indices_len = indicesShape[0];
|
||||
const size_t segments_num = outShape[0];
|
||||
const size_t inDimsSize = outShape.size();
|
||||
const size_t embDimsNum = outShape.size() - 1;
|
||||
|
||||
size_t embDepth = 1lu;
|
||||
for (size_t i = 1; i < outShape.size(); i++) {
|
||||
embDepth *= outShape[i];
|
||||
}
|
||||
memset(out, 0, shape_size(outShape) * sizeof(T));
|
||||
|
||||
bool with_weights = (weights != nullptr);
|
||||
|
||||
for (size_t index = 0; index < indices_len; index++) {
|
||||
size_t obi = segmentIds[index];
|
||||
if (obi >= segments_num)
|
||||
throw ngraph_error("Segment index could not be more than segments number");
|
||||
size_t dst_index = obi * embDepth;
|
||||
size_t src_index = indices[index] * embDepth;
|
||||
|
||||
if (with_weights) {
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] += embTable[src_index + i] * weights[index];
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] += embTable[src_index + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (defaultIndex != nullptr) {
|
||||
U defIndex = defaultIndex[0];
|
||||
if (defIndex < U(0) && defIndex >= embTableShape[0])
|
||||
throw ngraph_error(std::string("Invalid default index") + std::to_string(defIndex)) ;
|
||||
for (size_t obi = 0; obi < segments_num; obi++) {
|
||||
bool found = false;
|
||||
for (size_t index = 0; index < indices_len; index++) {
|
||||
if (segmentIds[index] == obi) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
size_t src_index = defIndex * embDepth;
|
||||
size_t dst_index = obi * embDepth;
|
||||
for (size_t i = 0lu; i < embDepth; i++) {
|
||||
out[dst_index + i] = embTable[src_index + i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} // embeddingSegmentsSum
|
||||
|
||||
} // reference
|
||||
} // runtime
|
||||
} // ngraph
|
||||
@@ -456,6 +456,24 @@ namespace
|
||||
EXPECT_FALSE(node.is_binary_elementwise_logical());
|
||||
}
|
||||
|
||||
void op_is_EmbeddingBagOffsetsSum()
|
||||
{
|
||||
op::EmbeddingBagOffsetsSum node;
|
||||
EXPECT_FALSE(node.is_unary_elementwise_arithmetic());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_arithmetic());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_comparison());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_logical());
|
||||
}
|
||||
|
||||
void op_is_EmbeddingBagPackedSum()
|
||||
{
|
||||
op::EmbeddingBagPackedSum node;
|
||||
EXPECT_FALSE(node.is_unary_elementwise_arithmetic());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_arithmetic());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_comparison());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_logical());
|
||||
}
|
||||
|
||||
void op_is_EmbeddingLookup()
|
||||
{
|
||||
op::EmbeddingLookup node;
|
||||
@@ -465,6 +483,15 @@ namespace
|
||||
EXPECT_FALSE(node.is_binary_elementwise_logical());
|
||||
}
|
||||
|
||||
void op_is_EmbeddingSegmentsSum()
|
||||
{
|
||||
op::EmbeddingSegmentsSum node;
|
||||
EXPECT_FALSE(node.is_unary_elementwise_arithmetic());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_arithmetic());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_comparison());
|
||||
EXPECT_FALSE(node.is_binary_elementwise_logical());
|
||||
}
|
||||
|
||||
void op_is_Equal()
|
||||
{
|
||||
op::Equal node;
|
||||
|
||||
@@ -54,7 +54,10 @@
|
||||
#include "ngraph/runtime/reference/dequantize.hpp"
|
||||
#include "ngraph/runtime/reference/dot.hpp"
|
||||
#include "ngraph/runtime/reference/elu.hpp"
|
||||
#include "ngraph/runtime/reference/embedding_bag_offsets_sum.hpp"
|
||||
#include "ngraph/runtime/reference/embedding_bag_packed_sum.hpp"
|
||||
#include "ngraph/runtime/reference/embedding_lookup.hpp"
|
||||
#include "ngraph/runtime/reference/embedding_segments_sum.hpp"
|
||||
#include "ngraph/runtime/reference/erf.hpp"
|
||||
#include "ngraph/runtime/reference/exp.hpp"
|
||||
#include "ngraph/runtime/reference/extract_image_patches.hpp"
|
||||
@@ -729,7 +732,100 @@ protected:
|
||||
else
|
||||
{
|
||||
throw ngraph_error(std::string("Unsupported index type ") + type.c_type_string() +
|
||||
std::string("in EmbeddingLookup"));
|
||||
std::string(" in EmbeddingLookup"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_TYPEID::EmbeddingBagOffsetsSum_v3:
|
||||
{
|
||||
const op::EmbeddingBagOffsetsSum* embed = static_cast<const op::EmbeddingBagOffsetsSum*>(&node);
|
||||
auto indicesType = embed->input(1).get_element_type();
|
||||
size_t indices_num = shape_size(embed->get_input_shape(1));
|
||||
|
||||
if (indicesType == element::u64 || indicesType == element::i64) {
|
||||
reference::embeddingBagOffsetsSum<T, size_t>(
|
||||
args[0]->get_data_ptr<const T>(),
|
||||
args[1]->get_data_ptr<const size_t>(),
|
||||
args[2]->get_data_ptr<const size_t>(),
|
||||
args.size() > 3 ? args[3]->get_data_ptr<const size_t>() : nullptr,
|
||||
args.size() > 4 ? args[4]->get_data_ptr<const T>() : nullptr,
|
||||
out[0]->get_data_ptr<T>(),
|
||||
indices_num,
|
||||
embed->get_shape());
|
||||
} else if (indicesType == element::u32 || indicesType == element::i32) {
|
||||
reference::embeddingBagOffsetsSum<T, unsigned>(
|
||||
args[0]->get_data_ptr<const T>(),
|
||||
args[1]->get_data_ptr<const unsigned>(),
|
||||
args[2]->get_data_ptr<const unsigned>(),
|
||||
args.size() > 3 ? args[3]->get_data_ptr<const unsigned>() : nullptr,
|
||||
args.size() > 4 ? args[4]->get_data_ptr<const T>() : nullptr,
|
||||
out[0]->get_data_ptr<T>(),
|
||||
indices_num,
|
||||
embed->get_shape());
|
||||
} else {
|
||||
throw ngraph_error(std::string("Unsupported index type ") + indicesType.c_type_string() +
|
||||
std::string(" in EmbeddingBagOffsetsSum"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_TYPEID::EmbeddingBagPackedSum_v3:
|
||||
{
|
||||
const op::EmbeddingBagPackedSum* embed = static_cast<const op::EmbeddingBagPackedSum*>(&node);
|
||||
auto indicesType = embed->input(1).get_element_type();
|
||||
|
||||
if (indicesType == element::u64 || indicesType == element::i64) {
|
||||
reference::embeddingBagPackedSum<T, size_t>(
|
||||
args[0]->get_data_ptr<const T>(),
|
||||
args[1]->get_data_ptr<const size_t>(),
|
||||
args.size() > 2 ? args[2]->get_data_ptr<const T>() : nullptr,
|
||||
out[0]->get_data_ptr<T>(),
|
||||
embed->get_input_shape(1),
|
||||
embed->get_shape());
|
||||
} else if (indicesType == element::u32 || indicesType == element::i32) {
|
||||
reference::embeddingBagPackedSum<T, unsigned>(
|
||||
args[0]->get_data_ptr<const T>(),
|
||||
args[1]->get_data_ptr<const unsigned>(),
|
||||
args.size() > 2 ? args[2]->get_data_ptr<const T>() : nullptr,
|
||||
out[0]->get_data_ptr<T>(),
|
||||
embed->get_input_shape(1),
|
||||
embed->get_shape());
|
||||
} else {
|
||||
throw ngraph_error(std::string("Unsupported index type ") + indicesType.c_type_string() +
|
||||
std::string(" in EmbeddingBagPackedSum"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_TYPEID::EmbeddingSegmentsSum_v3:
|
||||
{
|
||||
const op::EmbeddingSegmentsSum* embed = static_cast<const op::EmbeddingSegmentsSum*>(&node);
|
||||
auto indicesType = embed->input(1).get_element_type();
|
||||
size_t indices_num = shape_size(embed->get_input_shape(1));
|
||||
|
||||
if (indicesType == element::u64 || indicesType == element::i64) {
|
||||
reference::embeddingSegmentsSum<T, size_t>(
|
||||
args[0]->get_data_ptr<const T>(),
|
||||
args[1]->get_data_ptr<const size_t>(),
|
||||
args[2]->get_data_ptr<const size_t>(),
|
||||
args.size() > 4 ? args[4]->get_data_ptr<const size_t>() : nullptr,
|
||||
args.size() > 5 ? args[5]->get_data_ptr<const T>() : nullptr,
|
||||
out[0]->get_data_ptr<T>(),
|
||||
embed->get_input_shape(0),
|
||||
embed->get_input_shape(1),
|
||||
embed->get_shape());
|
||||
} else if (indicesType == element::u32 || indicesType == element::i32) {
|
||||
reference::embeddingSegmentsSum<T, unsigned>(
|
||||
args[0]->get_data_ptr<const T>(),
|
||||
args[1]->get_data_ptr<const unsigned>(),
|
||||
args[2]->get_data_ptr<const unsigned>(),
|
||||
args.size() > 4 ? args[4]->get_data_ptr<const unsigned>() : nullptr,
|
||||
args.size() > 5 ? args[5]->get_data_ptr<const T>() : nullptr,
|
||||
out[0]->get_data_ptr<T>(),
|
||||
embed->get_input_shape(0),
|
||||
embed->get_input_shape(1),
|
||||
embed->get_shape());
|
||||
} else {
|
||||
throw ngraph_error(std::string("Unsupported index type ") + indicesType.c_type_string() +
|
||||
std::string(" in EmbeddingSegmentsSum"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ NGRAPH_OP(LogicalNot, op::v1)
|
||||
#undef ID_SUFFIX
|
||||
|
||||
#define ID_SUFFIX(NAME) NAME##_v3
|
||||
NGRAPH_OP(EmbeddingBagOffsetsSum, op::v3)
|
||||
NGRAPH_OP(EmbeddingBagPackedSum, op::v3)
|
||||
NGRAPH_OP(EmbeddingSegmentsSum, op::v3)
|
||||
NGRAPH_OP(ExtractImagePatches, op::v3)
|
||||
NGRAPH_OP(ShapeOf, op::v3)
|
||||
NGRAPH_OP(NonZero, op::v3)
|
||||
|
||||
Reference in new issue
Block a user