DepthToSpace, SpaceToDepth layers optimizations (#706)
* [CPU] Updated DepthToSpace and SpaceToDepth layers to be conformant with the specification The patch also includes n[d]hwc layout support as well as some optimizations * [CPU][TESTS] Removed old DepthToSpace test since it doesn't corresponds to layer's specification * [nGraph] Utilize CommonOptimizations pass with custom transformations callback
This commit is contained in:
parent
01e60d057d
commit
3183c116d9
@ -83,7 +83,7 @@ InferenceEngine::ICNNNetwork::Ptr clDNNEngine::CloneNetwork(const InferenceEngin
|
||||
::ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc);
|
||||
|
||||
// Note: instead of running all Conversion Transformations you can make up your own transformation pipeline
|
||||
ngraph::pass::CommonOptimizations().run_on_function(nGraphFunc);
|
||||
ngraph::pass::CommonOptimizations(transformations_callback).run_on_function(nGraphFunc);
|
||||
ngraph::pass::ConvertOpSet3ToOpSet2(transformations_callback).run_on_function(nGraphFunc);
|
||||
ngraph::pass::ConvertOpSet2ToOpSet1(transformations_callback).run_on_function(nGraphFunc);
|
||||
ngraph::pass::ConvertOpSet1ToLegacy(transformations_callback).run_on_function(nGraphFunc);
|
||||
|
@ -1371,9 +1371,9 @@ void DepthToSpaceValidator::checkShapes(const CNNLayer* layer, const vector<Size
|
||||
|
||||
if (casted->block_size == 0) THROW_IE_EXCEPTION << layer->name << " Incorrect block_size parameter is zero!";
|
||||
|
||||
if (inShapes[0][inShapes[0].size() - 3] % (casted->block_size * casted->block_size))
|
||||
THROW_IE_EXCEPTION << layer->name
|
||||
<< " block_size parameter is incompatible with input tensor Color dimension size!";
|
||||
size_t numSpatialDims = inShapes[0].size() - 2;
|
||||
if (inShapes[0][1] % static_cast<size_t>(std::pow(casted->block_size, numSpatialDims)))
|
||||
THROW_IE_EXCEPTION << layer->name << " block_size parameter is incompatible with input tensor Color dimension size!";
|
||||
}
|
||||
|
||||
SpaceToDepthValidator::SpaceToDepthValidator(const std::string& _type): LayerValidator(_type) {}
|
||||
|
@ -82,6 +82,16 @@ Engine::LoadExeNetworkImpl(const InferenceEngine::ICNNNetwork &network, const st
|
||||
|
||||
if (clonedNetwork->getFunction()) {
|
||||
const auto transformations_callback = [](const std::shared_ptr<const ::ngraph::Node> &node) -> bool {
|
||||
// DepthToSpace node implementation supports only equal input/output tensors with rank <= 5
|
||||
if (auto dtsOp = std::dynamic_pointer_cast<const ::ngraph::opset3::DepthToSpace>(node)) {
|
||||
return dtsOp->input_value(0).get_shape().size() <= 5lu && dtsOp->input_value(0).get_shape().size() == dtsOp->get_output_shape(0).size();
|
||||
}
|
||||
|
||||
// SpaceToDepth node implementation supports only equal input/output tensors with rank <= 5
|
||||
if (auto stdOp = std::dynamic_pointer_cast<const ::ngraph::opset3::SpaceToDepth>(node)) {
|
||||
return stdOp->input_value(0).get_shape().size() <= 5lu && stdOp->input_value(0).get_shape().size() == stdOp->get_output_shape(0).size();
|
||||
}
|
||||
|
||||
return std::dynamic_pointer_cast<const ::ngraph::opset2::Gelu>(node) ||
|
||||
std::dynamic_pointer_cast<const ::ngraph::opset2::BatchToSpace>(node) ||
|
||||
std::dynamic_pointer_cast<const ::ngraph::opset2::SpaceToBatch>(node) ||
|
||||
@ -92,7 +102,7 @@ Engine::LoadExeNetworkImpl(const InferenceEngine::ICNNNetwork &network, const st
|
||||
::ngraph::op::GenericIE::DisableReshape noReshape(nGraphFunc);
|
||||
|
||||
// Note: instead of running all Conversion Transformations you can make up your own transformation pipeline
|
||||
ngraph::pass::CommonOptimizations().run_on_function(nGraphFunc);
|
||||
ngraph::pass::CommonOptimizations(transformations_callback).run_on_function(nGraphFunc);
|
||||
ngraph::pass::ConvertOpSet3ToOpSet2(transformations_callback).run_on_function(nGraphFunc);
|
||||
ngraph::pass::ConvertOpSet2ToOpSet1(transformations_callback).run_on_function(nGraphFunc);
|
||||
ngraph::pass::ConvertOpSet1ToLegacy(transformations_callback).run_on_function(nGraphFunc);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
#include "ie_parallel.hpp"
|
||||
|
||||
namespace InferenceEngine {
|
||||
@ -15,106 +16,202 @@ namespace Extensions {
|
||||
namespace Cpu {
|
||||
|
||||
class DepthToSpaceImpl: public ExtLayerBase {
|
||||
#define CNTR_SIZE 5
|
||||
enum class DepthToSpaceMode {
|
||||
BLOCKS_FIRST,
|
||||
DEPTH_FIRST
|
||||
};
|
||||
|
||||
public:
|
||||
explicit DepthToSpaceImpl(const CNNLayer* layer) {
|
||||
try {
|
||||
if (layer->insData.empty() || layer->outData.empty())
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect number of input/output edges!";
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << "' has incorrect number of input/output edges";
|
||||
|
||||
SizeVector src_dims = layer->insData[0].lock()->getTensorDesc().getDims();
|
||||
if (src_dims.size() < 3)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect number of input dimensions!";
|
||||
if (layer->insData[0].lock()->getTensorDesc().getPrecision() != Precision::FP32)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect input precision. Only F32 is supported!";
|
||||
inDims = layer->insData[0].lock()->getTensorDesc().getDims();
|
||||
if (inDims.size() < 3)
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << "' has incorrect number of input dimensions";
|
||||
|
||||
SizeVector dst_dims = layer->outData[0]->getTensorDesc().getDims();
|
||||
if (dst_dims.size() < 2)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect number of output dimensions!";
|
||||
if (layer->outData[0]->getTensorDesc().getPrecision() != Precision::FP32)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect output precision. Only F32 is supported!";
|
||||
if (inDims.size() > 5)
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << "' doesn't support dimensions with rank greater than 5";
|
||||
|
||||
size_t block_size = layer->GetParamAsUInt("block_size", 1);
|
||||
if (block_size == 0)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect block_size parameter is zero!";
|
||||
SizeVector outDims = layer->outData[0]->getTensorDesc().getDims();
|
||||
if (inDims.size() != outDims.size())
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << "' has incorrect number of input/output dimensions";
|
||||
|
||||
if (src_dims[src_dims.size() - 3] % (block_size * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " block_size parameter is incompatible with input tensor Color dimension size!";
|
||||
std::string modeString = layer->GetParamAsString("mode");
|
||||
if (modeString == "blocks_first") {
|
||||
mode = DepthToSpaceMode::BLOCKS_FIRST;
|
||||
} else if (modeString == "depth_first") {
|
||||
mode = DepthToSpaceMode::DEPTH_FIRST;
|
||||
} else {
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << "' doesn't support mode: " << modeString;
|
||||
}
|
||||
|
||||
if (dst_dims.size() > 2 && src_dims[src_dims.size() - 3] != (dst_dims[dst_dims.size() - 3] * block_size * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " Input/Output tensor Color dimension is incompatible with block_size!";
|
||||
blockSize = layer->GetParamAsUInt("block_size", 1);
|
||||
if (blockSize == 0)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect blockSize parameter is zero!";
|
||||
|
||||
if (dst_dims[dst_dims.size() - 2] != (src_dims[src_dims.size() - 2] * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " Input/Output tensor Height dimension is incompatible with block_size!";
|
||||
size_t numSpatialDims = inDims.size() - 2;
|
||||
blockStep = static_cast<size_t>(std::pow(blockSize, numSpatialDims));
|
||||
if (inDims[1] % blockStep)
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name <<
|
||||
"' has block_size parameter which is incompatible with input tensor channels dimension size";
|
||||
|
||||
if (dst_dims[dst_dims.size() - 1] != (src_dims[src_dims.size() - 1] * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " Input/Output tensor Width dimension is incompatible with block_size!";
|
||||
if (inDims[1] / blockStep != outDims[1])
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << " has incompatible input/output channels";
|
||||
|
||||
own_dims[0] = 1;
|
||||
for (size_t i = 0; i < (src_dims.size() - 3); i++)
|
||||
own_dims[0] *= src_dims[i];
|
||||
own_dims[1] = src_dims[src_dims.size() - 2];
|
||||
own_dims[2] = src_dims[src_dims.size() - 3] / block_size;
|
||||
own_dims[3] = src_dims[src_dims.size() - 1];
|
||||
own_dims[4] = block_size;
|
||||
for (int i = 0; i < numSpatialDims; i++) {
|
||||
if (inDims[i + 2] != outDims[i + 2] / blockSize)
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << " has incompatible spatial dims";
|
||||
}
|
||||
|
||||
size_t C = src_dims[src_dims.size() - 2] * src_dims[src_dims.size() - 1];
|
||||
ownStrides[0] = src_dims[src_dims.size() - 3] * C;
|
||||
ownStrides[1] = src_dims[src_dims.size() - 1];
|
||||
ownStrides[2] = block_size * C;
|
||||
ownStrides[3] = 1;
|
||||
ownStrides[4] = C;
|
||||
work_amount_dst = ownStrides[0] * own_dims[0];
|
||||
auto computePrc = layer->insData[0].lock()->getTensorDesc().getPrecision();
|
||||
const std::set<size_t> supported_precision_sizes = {1, 2, 4, 8};
|
||||
if (supported_precision_sizes.find(computePrc.size()) == supported_precision_sizes.end())
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << " doesn't support precision: " << computePrc.name();
|
||||
|
||||
addConfig(layer, { DataConfigurator(ConfLayout::PLN) }, { DataConfigurator(ConfLayout::PLN) });
|
||||
|
||||
if (inDims.size() == 4 || inDims.size() == 5) {
|
||||
LayerConfig config;
|
||||
DataConfig inConfig;
|
||||
inConfig.desc = TensorDesc(computePrc, inDims, inDims.size() == 4 ? NHWC : NDHWC);
|
||||
config.inConfs.push_back(inConfig);
|
||||
|
||||
DataConfig outConfig;
|
||||
outConfig.desc = TensorDesc(computePrc, outDims, outDims.size() == 4 ? NHWC : NDHWC);
|
||||
config.outConfs.push_back(outConfig);
|
||||
|
||||
config.dynBatchSupport = false;
|
||||
confs.push_back(config);
|
||||
}
|
||||
|
||||
LayerConfig config;
|
||||
DataConfig inConfig;
|
||||
inConfig.desc = TensorDesc(computePrc, inDims, InferenceEngine::TensorDesc::getLayoutByDims(inDims));
|
||||
config.inConfs.push_back(inConfig);
|
||||
|
||||
DataConfig outConfig;
|
||||
outConfig.desc = TensorDesc(computePrc, outDims, InferenceEngine::TensorDesc::getLayoutByDims(outDims));
|
||||
config.outConfs.push_back(outConfig);
|
||||
|
||||
config.dynBatchSupport = false;
|
||||
confs.push_back(config);
|
||||
} catch (InferenceEngine::details::InferenceEngineException &ex) {
|
||||
errorMsg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
StatusCode execute(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs, ResponseDesc *resp) noexcept override {
|
||||
const float *src_data = inputs[0]->cbuffer().as<const float *>() +
|
||||
inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
float* dst_data = outputs[0]->cbuffer().as<float *>() +
|
||||
outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
switch (inputs[0]->getTensorDesc().getPrecision().size()) {
|
||||
case 1: depthToSpaceKernel<PrecisionTrait<Precision::U8>::value_type>(inputs, outputs); break;
|
||||
case 2: depthToSpaceKernel<PrecisionTrait<Precision::U16>::value_type>(inputs, outputs); break;
|
||||
case 4: depthToSpaceKernel<PrecisionTrait<Precision::I32>::value_type>(inputs, outputs); break;
|
||||
case 8: depthToSpaceKernel<PrecisionTrait<Precision::U64>::value_type>(inputs, outputs); break;
|
||||
default: {
|
||||
if (resp) {
|
||||
std::string errorMsg = "DepthToSpace layer with name does not support precision '"
|
||||
+ std::string(inputs[0]->getTensorDesc().getPrecision().name()) + "'";
|
||||
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
|
||||
// Parallel
|
||||
parallel_nt(0, [&](const int ithr, const int nthr) {
|
||||
size_t start = 0, end = 0, src_idx = 0;
|
||||
size_t counters[CNTR_SIZE] = { 0 };
|
||||
splitter(work_amount_dst, nthr, ithr, start, end);
|
||||
for (int j = CNTR_SIZE - 1, i = start; j >= 0; j--) {
|
||||
counters[j] = i % own_dims[j];
|
||||
src_idx += counters[j] * ownStrides[j];
|
||||
i /= own_dims[j];
|
||||
}
|
||||
|
||||
for (size_t iwork = start, i = 1; iwork < end; ++iwork) {
|
||||
dst_data[iwork] = src_data[src_idx];
|
||||
for (int j = CNTR_SIZE - 1; j >= 0; j--) {
|
||||
counters[j]++;
|
||||
if (counters[j] < own_dims[j]) {
|
||||
src_idx += ownStrides[j];
|
||||
break;
|
||||
} else {
|
||||
counters[j] = i = 0;
|
||||
}
|
||||
}
|
||||
if (!i) {
|
||||
for (src_idx = 0; i < CNTR_SIZE; ++i)
|
||||
src_idx += counters[i] * ownStrides[i];
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t work_amount_dst;
|
||||
size_t own_dims[CNTR_SIZE];
|
||||
size_t ownStrides[CNTR_SIZE];
|
||||
std::vector<size_t> getShape5D(const SizeVector& shape) {
|
||||
std::vector<size_t> shape5D(5, 1);
|
||||
for (int i = 0; i < shape.size(); i++) {
|
||||
shape5D[i] = shape[i];
|
||||
}
|
||||
return shape5D;
|
||||
}
|
||||
|
||||
std::vector<size_t> getBlock3D(const SizeVector& shape, const SizeVector& shape5D) {
|
||||
std::vector<size_t> block3D(3, 1);
|
||||
for (int i = 0; i < shape.size() - 2; i++) {
|
||||
block3D[i] = blockSize;
|
||||
}
|
||||
return block3D;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void depthToSpaceKernel(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs) {
|
||||
const T *src_data = inputs[0]->cbuffer().as<const T *>() + inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
T* dst_data = outputs[0]->buffer().as<T *>() + outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
|
||||
auto shape5D = getShape5D(inDims);
|
||||
auto block3D = getBlock3D(inDims, shape5D);
|
||||
|
||||
size_t spatialStep = shape5D[2] * shape5D[3] * shape5D[4];
|
||||
size_t batchStep = shape5D[1] * spatialStep;
|
||||
|
||||
size_t srcChannels = shape5D[1];
|
||||
size_t dstChannels = srcChannels / blockStep;
|
||||
|
||||
size_t blockShift = mode == DepthToSpaceMode::BLOCKS_FIRST ? (dstChannels) : 1;
|
||||
size_t channelShift = mode == DepthToSpaceMode::BLOCKS_FIRST ? 1 : blockStep;
|
||||
|
||||
if (inputs[0]->getTensorDesc().getLayout() == NHWC || inputs[0]->getTensorDesc().getLayout() == NDHWC) {
|
||||
parallel_for2d(shape5D[0], shape5D[2], [&](size_t i0, size_t i2) {
|
||||
size_t srcIdx1 = i0 * batchStep;
|
||||
size_t dstIdx1 = i0 * batchStep;
|
||||
for (size_t b2 = 0; b2 < block3D[0]; b2++) {
|
||||
size_t srcIdx2 = srcIdx1 + i2 * shape5D[3] * shape5D[4] * srcChannels + b2 * block3D[1] * block3D[2] * blockShift;
|
||||
size_t dstIdx2 = dstIdx1 + (i2 * block3D[0] + b2) * shape5D[3] * block3D[1] * shape5D[4] * block3D[2] * dstChannels;
|
||||
for (size_t i3 = 0; i3 < shape5D[3]; i3++) {
|
||||
for (size_t b3 = 0; b3 < block3D[1]; b3++) {
|
||||
size_t srcIdx3 = srcIdx2 + i3 * shape5D[4] * srcChannels + b3 * block3D[2] * blockShift;
|
||||
size_t dstIdx3 = dstIdx2 + (i3 * block3D[1] + b3) * shape5D[4] * block3D[2] * dstChannels;
|
||||
for (size_t i4 = 0; i4 < shape5D[4]; i4++) {
|
||||
for (size_t b4 = 0; b4 < block3D[2]; b4++) {
|
||||
size_t srcIdx4 = srcIdx3 + i4 * srcChannels + b4 * blockShift;
|
||||
size_t dstIdx4 = dstIdx3 + (i4 * block3D[2] + b4) * dstChannels;
|
||||
for (size_t i1 = 0; i1 < dstChannels; i1++) {
|
||||
size_t srcIdx5 = srcIdx4 + i1 * channelShift;
|
||||
size_t dstIdx5 = dstIdx4 + i1;
|
||||
dst_data[dstIdx5] = src_data[srcIdx5];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
parallel_for2d(shape5D[0], dstChannels, [&](size_t i0, size_t i1) {
|
||||
size_t srcIdx1 = i0 * batchStep + i1 * channelShift * spatialStep;
|
||||
size_t dstIdx1 = i0 * batchStep + i1 * blockStep * spatialStep;
|
||||
for (size_t i2 = 0; i2 < shape5D[2]; i2++) {
|
||||
for (size_t b2 = 0; b2 < block3D[0]; b2++) {
|
||||
size_t srcIdx2 = srcIdx1 + i2 * shape5D[3] * shape5D[4] + b2 * block3D[1] * block3D[2] * blockShift * spatialStep;
|
||||
size_t dstIdx2 = dstIdx1 + (i2 * block3D[0] + b2) * shape5D[3] * block3D[1] * shape5D[4] * block3D[2];
|
||||
for (size_t i3 = 0; i3 < shape5D[3]; i3++) {
|
||||
for (size_t b3 = 0; b3 < block3D[1]; b3++) {
|
||||
size_t srcIdx3 = srcIdx2 + i3 * shape5D[4] + b3 * block3D[2] * blockShift * spatialStep;
|
||||
size_t dstIdx3 = dstIdx2 + (i3 * block3D[1] + b3) * shape5D[4] * block3D[2];
|
||||
for (size_t i4 = 0; i4 < shape5D[4]; i4++) {
|
||||
for (size_t b4 = 0; b4 < block3D[2]; b4++) {
|
||||
size_t srcIdx4 = srcIdx3 + i4 + b4 * blockShift * spatialStep;
|
||||
size_t dstIdx4 = dstIdx3 + i4 * block3D[2] + b4;
|
||||
dst_data[dstIdx4] = src_data[srcIdx4];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DepthToSpaceMode mode;
|
||||
SizeVector inDims;
|
||||
size_t blockSize;
|
||||
size_t blockStep;
|
||||
};
|
||||
|
||||
REG_FACTORY_FOR(DepthToSpaceImpl, DepthToSpace);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
#include "ie_parallel.hpp"
|
||||
|
||||
namespace InferenceEngine {
|
||||
@ -15,107 +16,202 @@ namespace Extensions {
|
||||
namespace Cpu {
|
||||
|
||||
class SpaceToDepthImpl: public ExtLayerBase {
|
||||
#define CNTR_SIZE 5
|
||||
enum class SpaceToDepthMode {
|
||||
BLOCKS_FIRST,
|
||||
DEPTH_FIRST
|
||||
};
|
||||
|
||||
public:
|
||||
explicit SpaceToDepthImpl(const CNNLayer* layer) {
|
||||
try {
|
||||
if (layer->insData.empty() || layer->outData.empty())
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect number of input/output edges!";
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << "' has incorrect number of input/output edges";
|
||||
|
||||
SizeVector src_dims = layer->insData[0].lock()->getTensorDesc().getDims();
|
||||
if (src_dims.size() < 2)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect number of input dimensions!";
|
||||
if (layer->insData[0].lock()->getTensorDesc().getPrecision() != Precision::FP32)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect input precision. Only F32 is supported!";
|
||||
SizeVector inDims = layer->insData[0].lock()->getTensorDesc().getDims();
|
||||
if (inDims.size() < 3)
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << "' has incorrect number of input dimensions";
|
||||
|
||||
SizeVector dst_dims = layer->outData[0]->getTensorDesc().getDims();
|
||||
if (dst_dims.size() < 3)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect number of output dimensions!";
|
||||
if (layer->outData[0]->getTensorDesc().getPrecision() != Precision::FP32)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect output precision. Only F32 is supported!";
|
||||
if (inDims.size() > 5)
|
||||
THROW_IE_EXCEPTION << "DepthToSpace layer with name '" << layer->name << "' doesn't support dimensions with rank greater than 5";
|
||||
|
||||
size_t block_size = layer->GetParamAsUInt("block_size", 1);
|
||||
if (block_size == 0)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect block_size parameter is zero!";
|
||||
outDims = layer->outData[0]->getTensorDesc().getDims();
|
||||
if (inDims.size() != outDims.size())
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << "' has incorrect number of input/output dimensions";
|
||||
|
||||
if (dst_dims[dst_dims.size() - 3] % (block_size * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " block_size parameter is incompatible with input tensor Color dimension size!";
|
||||
std::string modeString = layer->GetParamAsString("mode");
|
||||
if (modeString == "blocks_first") {
|
||||
mode = SpaceToDepthMode::BLOCKS_FIRST;
|
||||
} else if (modeString == "depth_first") {
|
||||
mode = SpaceToDepthMode::DEPTH_FIRST;
|
||||
} else {
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << "' doesn't support mode: " << modeString;
|
||||
}
|
||||
|
||||
if (src_dims.size() > 2 && dst_dims[dst_dims.size() - 3] != (src_dims[src_dims.size() - 3] * block_size * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " Input/Output tensor Color dimension is incompatible with block_size!";
|
||||
blockSize = layer->GetParamAsUInt("block_size", 1);
|
||||
if (blockSize == 0)
|
||||
THROW_IE_EXCEPTION << layer->name << " Incorrect blockSize parameter is zero!";
|
||||
|
||||
if (src_dims[src_dims.size() - 2] != (dst_dims[dst_dims.size() - 2] * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " Input/Output tensor Height dimension is incompatible with block_size!";
|
||||
size_t numSpatialDims = inDims.size() - 2;
|
||||
blockStep = static_cast<size_t>(std::pow(blockSize, numSpatialDims));
|
||||
if (outDims[1] % blockStep)
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name <<
|
||||
"' has block_size parameter which is incompatible with input tensor channels dimension size";
|
||||
|
||||
if (src_dims[src_dims.size() - 1] != (dst_dims[dst_dims.size() - 1] * block_size))
|
||||
THROW_IE_EXCEPTION << layer->name << " Input/Output tensor Width dimension is incompatible with block_size!";
|
||||
if (inDims[1] != outDims[1] / blockStep)
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << " has incompatible input/output channels";
|
||||
|
||||
own_dims[0] = 1;
|
||||
for (size_t i = 0; i < (dst_dims.size() - 3); i++)
|
||||
own_dims[0] *= dst_dims[i];
|
||||
own_dims[1] = dst_dims[dst_dims.size() - 2];
|
||||
own_dims[2] = dst_dims[dst_dims.size() - 3] / block_size;
|
||||
own_dims[3] = dst_dims[dst_dims.size() - 1];
|
||||
own_dims[4] = block_size;
|
||||
for (int i = 0; i < numSpatialDims; i++) {
|
||||
if (inDims[i + 2] / blockSize != outDims[i + 2])
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << " has incompatible spatial dims";
|
||||
}
|
||||
|
||||
size_t C = dst_dims[dst_dims.size() - 2] * dst_dims[dst_dims.size() - 1];
|
||||
ownStrides[0] = dst_dims[dst_dims.size() - 3] * C;
|
||||
ownStrides[1] = dst_dims[dst_dims.size() - 1];
|
||||
ownStrides[2] = block_size * C;
|
||||
ownStrides[3] = 1;
|
||||
ownStrides[4] = C;
|
||||
work_amount_dst = ownStrides[0] * own_dims[0];
|
||||
auto computePrc = layer->insData[0].lock()->getTensorDesc().getPrecision();
|
||||
const std::set<size_t> supported_precision_sizes = {1, 2, 4, 8};
|
||||
if (supported_precision_sizes.find(computePrc.size()) == supported_precision_sizes.end())
|
||||
THROW_IE_EXCEPTION << "SpaceToDepth layer with name '" << layer->name << " doesn't support precision: " << computePrc.name();
|
||||
|
||||
addConfig(layer, { DataConfigurator(ConfLayout::PLN) }, { DataConfigurator(ConfLayout::PLN) });
|
||||
|
||||
if (inDims.size() == 4 || inDims.size() == 5) {
|
||||
LayerConfig config;
|
||||
DataConfig inConfig;
|
||||
inConfig.desc = TensorDesc(computePrc, inDims, inDims.size() == 4 ? NHWC : NDHWC);
|
||||
config.inConfs.push_back(inConfig);
|
||||
|
||||
DataConfig outConfig;
|
||||
outConfig.desc = TensorDesc(computePrc, outDims, outDims.size() == 4 ? NHWC : NDHWC);
|
||||
config.outConfs.push_back(outConfig);
|
||||
|
||||
config.dynBatchSupport = false;
|
||||
confs.push_back(config);
|
||||
}
|
||||
|
||||
LayerConfig config;
|
||||
DataConfig inConfig;
|
||||
inConfig.desc = TensorDesc(computePrc, inDims, InferenceEngine::TensorDesc::getLayoutByDims(inDims));
|
||||
config.inConfs.push_back(inConfig);
|
||||
|
||||
DataConfig outConfig;
|
||||
outConfig.desc = TensorDesc(computePrc, outDims, InferenceEngine::TensorDesc::getLayoutByDims(outDims));
|
||||
config.outConfs.push_back(outConfig);
|
||||
|
||||
config.dynBatchSupport = false;
|
||||
confs.push_back(config);
|
||||
} catch (InferenceEngine::details::InferenceEngineException &ex) {
|
||||
errorMsg = ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
StatusCode execute(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs, ResponseDesc *resp) noexcept override {
|
||||
const float *src_data = inputs[0]->cbuffer().as<const float *>() +
|
||||
inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
float* dst_data = outputs[0]->cbuffer().as<float *>() +
|
||||
outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
switch (inputs[0]->getTensorDesc().getPrecision().size()) {
|
||||
case 1: spaceToDepthKernel<PrecisionTrait<Precision::U8>::value_type>(inputs, outputs); break;
|
||||
case 2: spaceToDepthKernel<PrecisionTrait<Precision::U16>::value_type>(inputs, outputs); break;
|
||||
case 4: spaceToDepthKernel<PrecisionTrait<Precision::I32>::value_type>(inputs, outputs); break;
|
||||
case 8: spaceToDepthKernel<PrecisionTrait<Precision::U64>::value_type>(inputs, outputs); break;
|
||||
default: {
|
||||
if (resp) {
|
||||
std::string errorMsg = "SpaceToDepth layer with name does not support precision '"
|
||||
+ std::string(inputs[0]->getTensorDesc().getPrecision().name()) + "'";
|
||||
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
|
||||
|
||||
// Parallel
|
||||
parallel_nt(0, [&](const int ithr, const int nthr) {
|
||||
size_t i, start = 0, end = 0, dst_idx = 0;
|
||||
size_t counters[CNTR_SIZE] = { 0 };
|
||||
splitter(work_amount_dst, nthr, ithr, start, end);
|
||||
i = start;
|
||||
for (int j = CNTR_SIZE - 1; j >= 0; j--) {
|
||||
counters[j] = i % own_dims[j];
|
||||
dst_idx += counters[j] * ownStrides[j];
|
||||
i /= own_dims[j];
|
||||
}
|
||||
|
||||
for (size_t iwork = start, i = 1; iwork < end; ++iwork) {
|
||||
dst_data[dst_idx] = src_data[iwork];
|
||||
for (int j = CNTR_SIZE - 1; j >= 0; j--) {
|
||||
counters[j]++;
|
||||
if (counters[j] < own_dims[j]) {
|
||||
dst_idx += ownStrides[j];
|
||||
break;
|
||||
} else {
|
||||
counters[j] = i = 0;
|
||||
}
|
||||
}
|
||||
if (!i) {
|
||||
for (dst_idx = 0; i < CNTR_SIZE; ++i)
|
||||
dst_idx += counters[i] * ownStrides[i];
|
||||
return GENERAL_ERROR;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t work_amount_dst;
|
||||
size_t own_dims[CNTR_SIZE];
|
||||
size_t ownStrides[CNTR_SIZE];
|
||||
std::vector<size_t> getShape5D(const SizeVector& shape) {
|
||||
std::vector<size_t> shape5D(5, 1);
|
||||
for (int i = 0; i < shape.size(); i++) {
|
||||
shape5D[i] = shape[i];
|
||||
}
|
||||
return shape5D;
|
||||
}
|
||||
|
||||
std::vector<size_t> getBlock3D(const SizeVector& shape, const SizeVector& shape5D) {
|
||||
std::vector<size_t> block3D(3, 1);
|
||||
for (int i = 0; i < shape.size() - 2; i++) {
|
||||
block3D[i] = blockSize;
|
||||
}
|
||||
return block3D;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void spaceToDepthKernel(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs) {
|
||||
const T *src_data = inputs[0]->cbuffer().as<const T *>() + inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
T* dst_data = outputs[0]->buffer().as<T *>() + outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
|
||||
|
||||
auto shape5D = getShape5D(outDims);
|
||||
auto block3D = getBlock3D(outDims, shape5D);
|
||||
|
||||
size_t spatialStep = shape5D[2] * shape5D[3] * shape5D[4];
|
||||
size_t batchStep = shape5D[1] * spatialStep;
|
||||
|
||||
size_t dstChannels = shape5D[1];
|
||||
size_t srcChannels = dstChannels / blockStep;
|
||||
|
||||
size_t blockShift = mode == SpaceToDepthMode::BLOCKS_FIRST ? (srcChannels) : 1;
|
||||
size_t channelShift = mode == SpaceToDepthMode::BLOCKS_FIRST ? 1 : blockStep;
|
||||
|
||||
if (inputs[0]->getTensorDesc().getLayout() == NHWC || inputs[0]->getTensorDesc().getLayout() == NDHWC) {
|
||||
parallel_for2d(shape5D[0], shape5D[2], [&](size_t i0, size_t i2) {
|
||||
size_t srcIdx1 = i0 * batchStep;
|
||||
size_t dstIdx1 = i0 * batchStep;
|
||||
for (size_t b2 = 0; b2 < block3D[0]; b2++) {
|
||||
size_t srcIdx2 = srcIdx1 + (i2 * block3D[0] + b2) * shape5D[3] * block3D[1] * shape5D[4] * block3D[2] * srcChannels;
|
||||
size_t dstIdx2 = dstIdx1 + i2 * shape5D[3] * shape5D[4] * dstChannels + b2 * block3D[1] * block3D[2] * blockShift;
|
||||
for (size_t i3 = 0; i3 < shape5D[3]; i3++) {
|
||||
for (size_t b3 = 0; b3 < block3D[1]; b3++) {
|
||||
size_t dstIdx3 = dstIdx2 + i3 * shape5D[4] * dstChannels + b3 * block3D[2] * blockShift;
|
||||
size_t srcIdx3 = srcIdx2 + (i3 * block3D[1] + b3) * shape5D[4] * block3D[2] * srcChannels;
|
||||
for (size_t i4 = 0; i4 < shape5D[4]; i4++) {
|
||||
for (size_t b4 = 0; b4 < block3D[2]; b4++) {
|
||||
size_t srcIdx4 = srcIdx3 + (i4 * block3D[2] + b4) * srcChannels;
|
||||
size_t dstIdx4 = dstIdx3 + i4 * dstChannels + b4 * blockShift;
|
||||
for (size_t i1 = 0; i1 < srcChannels; i1++) {
|
||||
size_t srcIdx5 = srcIdx4 + i1;
|
||||
size_t dstIdx5 = dstIdx4 + i1 * channelShift;
|
||||
dst_data[dstIdx5] = src_data[srcIdx5];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
parallel_for2d(shape5D[0], srcChannels, [&](size_t i0, size_t i1) {
|
||||
size_t srcIdx1 = i0 * batchStep + i1 * blockStep * spatialStep;
|
||||
size_t dstIdx1 = i0 * batchStep + i1 * channelShift * spatialStep;
|
||||
for (size_t i2 = 0; i2 < shape5D[2]; i2++) {
|
||||
for (size_t b2 = 0; b2 < block3D[0]; b2++) {
|
||||
size_t srcIdx2 = srcIdx1 + (i2 * block3D[0] + b2) * shape5D[3] * block3D[1] * shape5D[4] * block3D[2];
|
||||
size_t dstIdx2 = dstIdx1 + i2 * shape5D[3] * shape5D[4] + b2 * block3D[1] * block3D[2] * blockShift * spatialStep;
|
||||
for (size_t i3 = 0; i3 < shape5D[3]; i3++) {
|
||||
for (size_t b3 = 0; b3 < block3D[1]; b3++) {
|
||||
size_t srcIdx3 = srcIdx2 + (i3 * block3D[1] + b3) * shape5D[4] * block3D[2];
|
||||
size_t dstIdx3 = dstIdx2 + i3 * shape5D[4] + b3 * block3D[2] * blockShift * spatialStep;
|
||||
for (size_t i4 = 0; i4 < shape5D[4]; i4++) {
|
||||
for (size_t b4 = 0; b4 < block3D[2]; b4++) {
|
||||
size_t srcIdx4 = srcIdx3 + i4 * block3D[2] + b4;
|
||||
size_t dstIdx4 = dstIdx3 + i4 + b4 * blockShift * spatialStep;
|
||||
dst_data[dstIdx4] = src_data[srcIdx4];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
SpaceToDepthMode mode;
|
||||
SizeVector outDims;
|
||||
size_t blockSize;
|
||||
size_t blockStep;
|
||||
};
|
||||
|
||||
REG_FACTORY_FOR(SpaceToDepthImpl, SpaceToDepth);
|
||||
|
@ -21,9 +21,10 @@ class TRANSFORMATIONS_API CommonOptimizations;
|
||||
} // namespace pass
|
||||
} // namespace ngraph
|
||||
|
||||
class ngraph::pass::CommonOptimizations: public ngraph::pass::FunctionPass {
|
||||
class ngraph::pass::CommonOptimizations: public ngraph::pass::FunctionPass, public ngraph::pass::PassParam {
|
||||
public:
|
||||
explicit CommonOptimizations() : FunctionPass() {}
|
||||
explicit CommonOptimizations(const PassParam::param_callback & callback = PassParam::getDefaultCallback())
|
||||
: FunctionPass(), PassParam(callback) {}
|
||||
|
||||
bool run_on_function(std::shared_ptr<ngraph::Function> f) override;
|
||||
};
|
||||
|
@ -20,11 +20,17 @@
|
||||
|
||||
bool ngraph::pass::CommonOptimizations::run_on_function(std::shared_ptr<ngraph::Function> f) {
|
||||
ngraph::pass::Manager CommonOptimizations;
|
||||
std::vector<std::shared_ptr<ngraph::pass::PassBase> > transforms;
|
||||
|
||||
#define NGRAPH_PASS(NAME, NAMESPACE) CommonOptimizations.register_pass<NAMESPACE::NAME>();
|
||||
#define NGRAPH_PASS(NAME, NAMESPACE) transforms.push_back(CommonOptimizations.register_pass<NAMESPACE::NAME>());
|
||||
#include <transformations/common_optimizations/common_optimizations_tbl.hpp>
|
||||
#undef NGRAPH_PASS
|
||||
|
||||
for (auto & t : transforms) {
|
||||
if (auto t_param = std::dynamic_pointer_cast<PassParam>(t)) {
|
||||
t_param->setCallback(transformation_callback);
|
||||
}
|
||||
}
|
||||
CommonOptimizations.run_passes(f);
|
||||
return true;
|
||||
}
|
||||
|
@ -91,10 +91,6 @@ void ngraph::pass::DepthToSpaceFusion::depth_to_space_fusion() {
|
||||
auto reshape_after = std::make_shared<ngraph::opset3::Reshape> (permute, input3, false);
|
||||
|
||||
ngraph::graph_rewrite_callback callback = [this](pattern::Matcher& m) {
|
||||
if (!transformation_callback(std::make_shared<ngraph::opset3::DepthToSpace>())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto reshape_after = std::dynamic_pointer_cast<ngraph::opset3::Reshape>(m.get_match_root());
|
||||
if (!reshape_after) {
|
||||
return false;
|
||||
@ -157,6 +153,11 @@ void ngraph::pass::DepthToSpaceFusion::depth_to_space_fusion() {
|
||||
std::make_shared<ngraph::opset3::DepthToSpace>(reshape_before->input_value(0), mode, block_size);
|
||||
depth_to_space->set_friendly_name(reshape_after->get_friendly_name());
|
||||
ngraph::copy_runtime_info({reshape_before, permute, reshape_after}, depth_to_space);
|
||||
|
||||
if (!transformation_callback(depth_to_space)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ngraph::replace_node(reshape_after, depth_to_space);
|
||||
return true;
|
||||
};
|
||||
|
@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <ngraph/opsets/opset3.hpp>
|
||||
|
||||
#include "single_layer_tests/depth_to_space.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
using namespace ngraph::opset3;
|
||||
|
||||
namespace {
|
||||
const std::vector<InferenceEngine::Precision> inputPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::U8,
|
||||
InferenceEngine::Precision::I16,
|
||||
};
|
||||
|
||||
const std::vector<DepthToSpace::DepthToSpaceMode> modes = {
|
||||
DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST,
|
||||
DepthToSpace::DepthToSpaceMode::DEPTH_FIRST};
|
||||
|
||||
const std::vector<std::vector<size_t >> inputShapesBS2 = {
|
||||
{1, 4, 1, 1}, {1, 4, 2, 2}, {1, 4, 3, 3}, {2, 32, 3, 3}, {2, 16, 5, 4},
|
||||
{1, 8, 1, 1, 1}, {1, 8, 2, 2, 2}, {1, 8, 3, 3, 3}, {2, 32, 3, 3, 3}, {2, 16, 5, 4, 6}};
|
||||
|
||||
const auto DepthToSpaceBS2 = ::testing::Combine(
|
||||
::testing::ValuesIn(inputShapesBS2),
|
||||
::testing::ValuesIn(inputPrecisions),
|
||||
::testing::ValuesIn(modes),
|
||||
::testing::Values(2),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DepthToSpaceBS2, DepthToSpaceLayerTest, DepthToSpaceBS2, DepthToSpaceLayerTest::getTestCaseName);
|
||||
|
||||
const std::vector<std::vector<size_t >> inputShapesBS3 = {
|
||||
{1, 9, 1, 1}, {1, 9, 2, 2}, {1, 9, 3, 3}, {2, 36, 3, 3}, {2, 27, 5, 4},
|
||||
{1, 27, 1, 1, 1}, {1, 27, 2, 2, 2}, {1, 27, 3, 3, 3}, {2, 108, 3, 3, 3}, {2, 54, 5, 4, 6}};
|
||||
|
||||
const auto DepthToSpaceBS3 = ::testing::Combine(
|
||||
::testing::ValuesIn(inputShapesBS3),
|
||||
::testing::ValuesIn(inputPrecisions),
|
||||
::testing::ValuesIn(modes),
|
||||
::testing::Values(3),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(DepthToSpaceBS3, DepthToSpaceLayerTest, DepthToSpaceBS3, DepthToSpaceLayerTest::getTestCaseName);
|
||||
|
||||
} // namespace
|
@ -0,0 +1,53 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <vector>
|
||||
#include <ngraph/opsets/opset3.hpp>
|
||||
|
||||
#include "single_layer_tests/space_to_depth.hpp"
|
||||
#include "common_test_utils/test_constants.hpp"
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
using namespace ngraph::opset3;
|
||||
|
||||
namespace {
|
||||
const std::vector<InferenceEngine::Precision> inputPrecisions = {
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::U8,
|
||||
InferenceEngine::Precision::I16,
|
||||
};
|
||||
|
||||
const std::vector<SpaceToDepth::SpaceToDepthMode> modes = {
|
||||
SpaceToDepth::SpaceToDepthMode::BLOCKS_FIRST,
|
||||
SpaceToDepth::SpaceToDepthMode::DEPTH_FIRST};
|
||||
|
||||
const std::vector<std::vector<size_t >> inputShapesBS2 = {
|
||||
{1, 1, 2, 2}, {1, 1, 4, 4}, {1, 1, 6, 6}, {2, 8, 6, 6}, {2, 4, 10, 8},
|
||||
{1, 1, 2, 2, 2}, {1, 1, 4, 4, 4}, {1, 1, 6, 6, 6}, {2, 8, 6, 6, 6}, {2, 4, 10, 8, 12}};
|
||||
|
||||
const auto SpaceToDepthBS2 = ::testing::Combine(
|
||||
::testing::ValuesIn(inputShapesBS2),
|
||||
::testing::ValuesIn(inputPrecisions),
|
||||
::testing::ValuesIn(modes),
|
||||
::testing::Values(2),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SpaceToDepthBS2, SpaceToDepthLayerTest, SpaceToDepthBS2, SpaceToDepthLayerTest::getTestCaseName);
|
||||
|
||||
const std::vector<std::vector<size_t >> inputShapesBS3 = {
|
||||
{1, 1, 3, 3}, {1, 1, 6, 6}, {1, 1, 9, 9}, {2, 4, 9, 9}, {2, 3, 15, 12},
|
||||
{1, 1, 3, 3, 3}, {1, 1, 6, 6, 6}, {1, 1, 9, 9, 9}, {2, 4, 9, 9, 9}, {2, 3, 15, 12, 18}};
|
||||
|
||||
const auto SpaceToDepthBS3 = ::testing::Combine(
|
||||
::testing::ValuesIn(inputShapesBS3),
|
||||
::testing::ValuesIn(inputPrecisions),
|
||||
::testing::ValuesIn(modes),
|
||||
::testing::Values(3),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(SpaceToDepthBS3, SpaceToDepthLayerTest, SpaceToDepthBS3, SpaceToDepthLayerTest::getTestCaseName);
|
||||
|
||||
} // namespace
|
@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
using depthToSpaceParamsTuple = typename std::tuple<
|
||||
std::vector<size_t>, // Input shape
|
||||
InferenceEngine::Precision, // Input precision
|
||||
ngraph::opset3::DepthToSpace::DepthToSpaceMode, // Mode
|
||||
std::size_t, // Block size
|
||||
std::string>; // Device name>
|
||||
|
||||
class DepthToSpaceLayerTest : public testing::WithParamInterface<depthToSpaceParamsTuple>,
|
||||
public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(const testing::TestParamInfo<depthToSpaceParamsTuple> &obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "functional_test_utils/layer_test_utils.hpp"
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
using spaceToDepthParamsTuple = typename std::tuple<
|
||||
std::vector<size_t>, // Input shape
|
||||
InferenceEngine::Precision, // Input precision
|
||||
ngraph::opset3::SpaceToDepth::SpaceToDepthMode, // Mode
|
||||
std::size_t, // Block size
|
||||
std::string>; // Device name>
|
||||
|
||||
class SpaceToDepthLayerTest : public testing::WithParamInterface<spaceToDepthParamsTuple>,
|
||||
public LayerTestsUtils::LayerTestsCommon {
|
||||
public:
|
||||
static std::string getTestCaseName(const testing::TestParamInfo<spaceToDepthParamsTuple> &obj);
|
||||
|
||||
protected:
|
||||
void SetUp() override;
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <ie_core.hpp>
|
||||
#include <ngraph_functions/builders.hpp>
|
||||
|
||||
#include "functional_test_utils/blob_utils.hpp"
|
||||
#include "functional_test_utils/precision_utils.hpp"
|
||||
#include "common_test_utils/common_utils.hpp"
|
||||
|
||||
#include "single_layer_tests/depth_to_space.hpp"
|
||||
|
||||
using namespace ngraph::opset3;
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
static inline std::string DepthToSpaceModeToString(const DepthToSpace::DepthToSpaceMode& mode) {
|
||||
static std::map<DepthToSpace::DepthToSpaceMode, std::string> names = {
|
||||
{DepthToSpace::DepthToSpaceMode::BLOCKS_FIRST, "BLOCKS_FIRST"},
|
||||
{DepthToSpace::DepthToSpaceMode::DEPTH_FIRST, "DEPTH_FIRST"},
|
||||
};
|
||||
|
||||
auto i = names.find(mode);
|
||||
if (i != names.end())
|
||||
return i->second;
|
||||
else
|
||||
throw std::runtime_error("Unsupported DepthToSpaceMode");
|
||||
}
|
||||
|
||||
std::string DepthToSpaceLayerTest::getTestCaseName(const testing::TestParamInfo<depthToSpaceParamsTuple> &obj) {
|
||||
std::vector<size_t> inShape;
|
||||
DepthToSpace::DepthToSpaceMode mode;
|
||||
std::size_t blockSize;
|
||||
InferenceEngine::Precision inputPrecision;
|
||||
std::string targetName;
|
||||
std::tie(inShape, inputPrecision, mode, blockSize, targetName) = obj.param;
|
||||
std::ostringstream result;
|
||||
result << "IS=" << CommonTestUtils::vec2str(inShape) << "_";
|
||||
result << "inPrc=" << inputPrecision.name() << "_";
|
||||
result << "M=" << DepthToSpaceModeToString(mode) << "_";
|
||||
result << "BS=" << blockSize << "_";
|
||||
result << "targetDevice=" << targetName << "_";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void DepthToSpaceLayerTest::SetUp() {
|
||||
std::vector<size_t> inShape;
|
||||
DepthToSpace::DepthToSpaceMode mode;
|
||||
std::size_t blockSize;
|
||||
InferenceEngine::Precision inputPrecision;
|
||||
std::tie(inShape, inputPrecision, mode, blockSize, targetDevice) = this->GetParam();
|
||||
auto inPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inputPrecision);
|
||||
auto params = ngraph::builder::makeParams(inPrc, {inShape});
|
||||
auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(params));
|
||||
auto d2s = ngraph::builder::makeDepthToSpace(paramOuts[0], mode, blockSize);
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(d2s)};
|
||||
function = std::make_shared<ngraph::Function>(results, params, "DepthToSpace");
|
||||
}
|
||||
|
||||
TEST_P(DepthToSpaceLayerTest, CompareWithRefs) {
|
||||
Run();
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
@ -0,0 +1,72 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include <ie_core.hpp>
|
||||
#include <ngraph_functions/builders.hpp>
|
||||
|
||||
#include "functional_test_utils/blob_utils.hpp"
|
||||
#include "functional_test_utils/precision_utils.hpp"
|
||||
#include "common_test_utils/common_utils.hpp"
|
||||
|
||||
#include "single_layer_tests/space_to_depth.hpp"
|
||||
|
||||
using namespace ngraph::opset3;
|
||||
|
||||
namespace LayerTestsDefinitions {
|
||||
|
||||
static inline std::string SpaceToDepthModeToString(const SpaceToDepth::SpaceToDepthMode& mode) {
|
||||
static std::map<SpaceToDepth::SpaceToDepthMode, std::string> names = {
|
||||
{SpaceToDepth::SpaceToDepthMode::BLOCKS_FIRST, "BLOCKS_FIRST"},
|
||||
{SpaceToDepth::SpaceToDepthMode::DEPTH_FIRST, "DEPTH_FIRST"},
|
||||
};
|
||||
|
||||
auto i = names.find(mode);
|
||||
if (i != names.end())
|
||||
return i->second;
|
||||
else
|
||||
throw std::runtime_error("Unsupported SpaceToDepthMode");
|
||||
}
|
||||
|
||||
std::string SpaceToDepthLayerTest::getTestCaseName(const testing::TestParamInfo<spaceToDepthParamsTuple> &obj) {
|
||||
std::vector<size_t> inShape;
|
||||
SpaceToDepth::SpaceToDepthMode mode;
|
||||
std::size_t blockSize;
|
||||
InferenceEngine::Precision inputPrecision;
|
||||
std::string targetName;
|
||||
std::tie(inShape, inputPrecision, mode, blockSize, targetName) = obj.param;
|
||||
std::ostringstream result;
|
||||
result << "IS=" << CommonTestUtils::vec2str(inShape) << "_";
|
||||
result << "inPrc=" << inputPrecision.name() << "_";
|
||||
result << "M=" << SpaceToDepthModeToString(mode) << "_";
|
||||
result << "BS=" << blockSize << "_";
|
||||
result << "targetDevice=" << targetName << "_";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
void SpaceToDepthLayerTest::SetUp() {
|
||||
std::vector<size_t> inShape;
|
||||
SpaceToDepth::SpaceToDepthMode mode;
|
||||
std::size_t blockSize;
|
||||
InferenceEngine::Precision inputPrecision;
|
||||
std::tie(inShape, inputPrecision, mode, blockSize, targetDevice) = this->GetParam();
|
||||
auto inPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(inputPrecision);
|
||||
auto params = ngraph::builder::makeParams(inPrc, {inShape});
|
||||
auto paramOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(params));
|
||||
auto s2d = ngraph::builder::makeSpaceToDepth(paramOuts[0], mode, blockSize);
|
||||
ngraph::ResultVector results{std::make_shared<ngraph::opset1::Result>(s2d)};
|
||||
function = std::make_shared<ngraph::Function>(results, params, "SpaceToDepth");
|
||||
}
|
||||
|
||||
TEST_P(SpaceToDepthLayerTest, CompareWithRefs) {
|
||||
Run();
|
||||
};
|
||||
|
||||
} // namespace LayerTestsDefinitions
|
@ -212,6 +212,13 @@ std::shared_ptr<ngraph::Node> makeEmbeddingSegmentsSum(
|
||||
bool with_weights,
|
||||
bool with_default_index);
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeDepthToSpace(const ngraph::Output<Node> &in,
|
||||
ngraph::opset3::DepthToSpace::DepthToSpaceMode mode,
|
||||
size_t blockSize);
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeSpaceToDepth(const ngraph::Output<Node> &in,
|
||||
ngraph::opset3::SpaceToDepth::SpaceToDepthMode mode,
|
||||
size_t blockSize);
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
||||
|
@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeDepthToSpace(const ngraph::Output<Node> &in,
|
||||
ngraph::opset3::DepthToSpace::DepthToSpaceMode mode,
|
||||
size_t blockSize) {
|
||||
auto dtsNode = std::make_shared<ngraph::opset3::DepthToSpace>(in, mode, blockSize);
|
||||
return dtsNode;
|
||||
}
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph_functions/builders.hpp"
|
||||
|
||||
namespace ngraph {
|
||||
namespace builder {
|
||||
|
||||
std::shared_ptr<ngraph::Node> makeSpaceToDepth(const ngraph::Output<Node> &in,
|
||||
ngraph::opset3::SpaceToDepth::SpaceToDepthMode mode,
|
||||
size_t blockSize) {
|
||||
auto dtsNode = std::make_shared<ngraph::opset3::SpaceToDepth>(in, mode, blockSize);
|
||||
return dtsNode;
|
||||
}
|
||||
|
||||
} // namespace builder
|
||||
} // namespace ngraph
|
@ -1,511 +0,0 @@
|
||||
// Copyright (C) 2018-2020 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "test_graph.hpp"
|
||||
|
||||
#include "single_layer_common.hpp"
|
||||
#include "tests_common.hpp"
|
||||
#include <ie_core.hpp>
|
||||
|
||||
|
||||
using namespace ::testing;
|
||||
using namespace std;
|
||||
using namespace mkldnn;
|
||||
|
||||
struct depth_to_space_test_params {
|
||||
InferenceEngine::SizeVector in_shape;
|
||||
size_t block_size;
|
||||
InferenceEngine::SizeVector out_shape;
|
||||
|
||||
std::vector<float> reference;
|
||||
std::vector<std::function<void(MKLDNNPlugin::PrimitiveDescInfo)>> comp;
|
||||
};
|
||||
|
||||
void ref_depth_to_space(
|
||||
InferenceEngine::TBlob<float> &src,
|
||||
InferenceEngine::TBlob<float> &dst,
|
||||
size_t block_size
|
||||
) {
|
||||
size_t i;
|
||||
const float *src_data = src.data();
|
||||
InferenceEngine::SizeVector src_dims = src.getTensorDesc().getDims();
|
||||
InferenceEngine::SizeVector srcStrides = src.getTensorDesc().getBlockingDesc().getStrides();
|
||||
float* dst_data = dst.data();
|
||||
InferenceEngine::SizeVector dst_dims = dst.getTensorDesc().getDims();
|
||||
InferenceEngine::SizeVector dstStrides = dst.getTensorDesc().getBlockingDesc().getStrides();
|
||||
|
||||
if (src_dims.size() < 3)
|
||||
FAIL() << " Incorrect number of input dimensions!";
|
||||
|
||||
if (dst_dims.size() < 2)
|
||||
FAIL() << " Incorrect number of output dimensions!";
|
||||
|
||||
if (block_size == 0)
|
||||
FAIL() << " Incorrect block_size parameter is zero!";
|
||||
|
||||
if (src_dims[src_dims.size() - 3] % (block_size * block_size))
|
||||
FAIL() << " block_size parameter is incompatible with input tensor Color dimension size!";
|
||||
|
||||
if (dst_dims.size() > 2 && src_dims[src_dims.size() - 3] != (dst_dims[dst_dims.size() - 3] * block_size * block_size))
|
||||
FAIL() << " Input/Output tensor Color dimension is incompatible with block_size!";
|
||||
|
||||
if (dst_dims[dst_dims.size() - 2] != (src_dims[src_dims.size() - 2] * block_size))
|
||||
FAIL() << " Input/Output tensor Height dimension is incompatible with block_size!";
|
||||
|
||||
if (dst_dims[dst_dims.size() - 1] != (src_dims[src_dims.size() - 1] * block_size))
|
||||
FAIL() << " Input/Output tensor Width dimension is incompatible with block_size!";
|
||||
|
||||
size_t X = 1;
|
||||
for (i = 0; i < (src_dims.size() - 3); i++)
|
||||
X *= src_dims[i];
|
||||
|
||||
size_t C = src_dims[src_dims.size() - 3];
|
||||
size_t H = src_dims[src_dims.size() - 2];
|
||||
size_t W = src_dims[src_dims.size() - 1];
|
||||
|
||||
for (size_t x = 0, k = 0; x < X; ++x) {
|
||||
for (size_t h = 0; h < H; ++h) {
|
||||
for (size_t c = 0; c < C; c += block_size) {
|
||||
for (size_t w = 0; w < W; ++w) {
|
||||
for (size_t b = 0; b < block_size; ++b) {
|
||||
size_t idx = x * C*H*W + (c + b) * H*W + h * W + w;
|
||||
dst_data[k++] = src_data[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ref_space_to_depth(
|
||||
InferenceEngine::TBlob<float> &src,
|
||||
InferenceEngine::TBlob<float> &dst,
|
||||
size_t block_size
|
||||
) {
|
||||
size_t i;
|
||||
const float *src_data = src.data();
|
||||
InferenceEngine::SizeVector src_dims = src.getTensorDesc().getDims();
|
||||
InferenceEngine::SizeVector srcStrides = src.getTensorDesc().getBlockingDesc().getStrides();
|
||||
float* dst_data = dst.data();
|
||||
InferenceEngine::SizeVector dst_dims = dst.getTensorDesc().getDims();
|
||||
InferenceEngine::SizeVector dstStrides = dst.getTensorDesc().getBlockingDesc().getStrides();
|
||||
|
||||
if (dst_dims.size() < 3)
|
||||
FAIL() << " Incorrect number of output dimensions!";
|
||||
|
||||
if (src_dims.size() < 2)
|
||||
FAIL() << " Incorrect number of input dimensions!";
|
||||
|
||||
if (block_size == 0)
|
||||
FAIL() << " Incorrect block_size parameter is zero!";
|
||||
|
||||
if (dst_dims[dst_dims.size() - 3] % (block_size * block_size))
|
||||
FAIL() << " block_size parameter is incompatible with input tensor Color dimension size!";
|
||||
|
||||
if (src_dims.size() > 2 && dst_dims[dst_dims.size() - 3] != (src_dims[dst_dims.size() - 3] * block_size * block_size))
|
||||
FAIL() << " Input/Output tensor Color dimension is incompatible with block_size!";
|
||||
|
||||
if (src_dims[src_dims.size() - 2] != (dst_dims[dst_dims.size() - 2] * block_size))
|
||||
FAIL() << " Input/Output tensor Height dimension is incompatible with block_size!";
|
||||
|
||||
if (src_dims[src_dims.size() - 1] != (dst_dims[dst_dims.size() - 1] * block_size))
|
||||
FAIL() << " Input/Output tensor Width dimension is incompatible with block_size!";
|
||||
|
||||
size_t X = 1;
|
||||
for (i = 0; i < (dst_dims.size() - 3); i++)
|
||||
X *= dst_dims[i];
|
||||
|
||||
size_t C = dst_dims[dst_dims.size() - 3];
|
||||
size_t H = dst_dims[dst_dims.size() - 2];
|
||||
size_t W = dst_dims[dst_dims.size() - 1];
|
||||
|
||||
for (size_t x = 0, k = 0; x < X; ++x) {
|
||||
for (size_t h = 0; h < H; ++h) {
|
||||
for (size_t c = 0; c < C; c += block_size) {
|
||||
for (size_t w = 0; w < W; ++w) {
|
||||
for (size_t b = 0; b < block_size; ++b) {
|
||||
size_t idx = x * C*H*W + (c + b) * H*W + h * W + w;
|
||||
dst_data[idx] = src_data[k++];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MKLDNNCPUExtDepthToSpaceTests : public TestsCommon, public WithParamInterface<depth_to_space_test_params> {
|
||||
std::string model_t = R"V0G0N(
|
||||
<net Name="DepthToSpace_net" version="2" precision="FP32" batch="1">
|
||||
<layers>
|
||||
<layer name="input" type="Input" precision="FP32" id="1">
|
||||
<output>
|
||||
<port id="1">
|
||||
_IN_
|
||||
</port>
|
||||
</output>s
|
||||
</layer>
|
||||
<layer name="output" id="2" type="DepthToSpace" precision="FP32">
|
||||
<data block_size="_BS_"/>
|
||||
<input>
|
||||
<port id="1">
|
||||
_IN_
|
||||
</port>
|
||||
</input>
|
||||
<output>
|
||||
<port id="2">
|
||||
_OUT_
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
</layers>
|
||||
<edges>
|
||||
<edge from-layer="1" from-port="1" to-layer="2" to-port="1"/>
|
||||
</edges>
|
||||
</net>
|
||||
)V0G0N";
|
||||
|
||||
std::string getModel(depth_to_space_test_params p) {
|
||||
std::string model = model_t;
|
||||
std::string in_shape, out_shape;
|
||||
|
||||
for (size_t i = 0; i < p.in_shape.size(); i++) {
|
||||
in_shape += "<dim>";
|
||||
in_shape += std::to_string(p.in_shape[i]) + "</dim>\n";
|
||||
}
|
||||
for (size_t i = 0; i < p.out_shape.size(); i++) {
|
||||
out_shape += "<dim>";
|
||||
out_shape += std::to_string(p.out_shape[i]) + "</dim>\n";
|
||||
}
|
||||
REPLACE_WITH_STR(model, "_IN_", in_shape);
|
||||
REPLACE_WITH_STR(model, "_OUT_", out_shape);
|
||||
REPLACE_WITH_NUM(model, "_BS_", p.block_size);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void TearDown() {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
try {
|
||||
TestsCommon::SetUp();
|
||||
depth_to_space_test_params p = ::testing::WithParamInterface<depth_to_space_test_params>::GetParam();
|
||||
std::string model = getModel(p);
|
||||
|
||||
InferenceEngine::Core core;
|
||||
InferenceEngine::CNNNetwork network;
|
||||
ASSERT_NO_THROW(network = core.ReadNetwork(model, InferenceEngine::Blob::CPtr()));
|
||||
|
||||
MKLDNNGraphTestClass graph;
|
||||
graph.CreateGraph(network);
|
||||
|
||||
// Output Data
|
||||
InferenceEngine::OutputsDataMap out;
|
||||
out = network.getOutputsInfo();
|
||||
InferenceEngine::BlobMap outputBlobs;
|
||||
|
||||
std::pair<std::string, InferenceEngine::DataPtr> item = *out.begin();
|
||||
|
||||
InferenceEngine::TBlob<float>::Ptr output;
|
||||
output = InferenceEngine::make_shared_blob<float>(item.second->getTensorDesc());
|
||||
output->allocate();
|
||||
outputBlobs[item.first] = output;
|
||||
|
||||
// Output Reference
|
||||
InferenceEngine::TBlob<float> dst_ref(item.second->getTensorDesc());
|
||||
dst_ref.allocate();
|
||||
|
||||
// Input Data
|
||||
InferenceEngine::Blob::Ptr src;
|
||||
src = InferenceEngine::make_shared_blob<float>({ InferenceEngine::Precision::FP32, p.in_shape, InferenceEngine::TensorDesc::getLayoutByDims(p.in_shape) });
|
||||
src->allocate();
|
||||
fill_data_dbgval(src->buffer(), src->size());
|
||||
auto * srcPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(src.get());
|
||||
if (srcPtr == nullptr)
|
||||
FAIL() << "Cannot cast blob to TBlob<float>.";
|
||||
|
||||
// Check results
|
||||
InferenceEngine::SizeVector out_dims;
|
||||
ref_depth_to_space(*srcPtr, dst_ref, p.block_size);
|
||||
|
||||
// Check results
|
||||
if(p.reference.size())
|
||||
if (memcmp(dst_ref.data(), &p.reference[0], p.reference.size() * sizeof(float)) != 0)
|
||||
FAIL() << "Wrong result with compare TF reference!";
|
||||
|
||||
InferenceEngine::BlobMap srcs;
|
||||
srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("input", src));
|
||||
|
||||
// Infer
|
||||
graph.Infer(srcs, outputBlobs);
|
||||
compare(*output, dst_ref);
|
||||
} catch (const InferenceEngine::details::InferenceEngineException &e) {
|
||||
FAIL() << e.what();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MKLDNNCPUExtSpaceToDepthTests : public TestsCommon, public WithParamInterface<depth_to_space_test_params> {
|
||||
std::string model_t = R"V0G0N(
|
||||
<net Name="SpaceToDepth_net" version="2" precision="FP32" batch="1">
|
||||
<layers>
|
||||
<layer name="input" type="Input" precision="FP32" id="1">
|
||||
<output>
|
||||
<port id="1">
|
||||
_IN_
|
||||
</port>
|
||||
</output>s
|
||||
</layer>
|
||||
<layer name="output" id="2" type="SpaceToDepth" precision="FP32">
|
||||
<data block_size="_BS_"/>
|
||||
<input>
|
||||
<port id="1">
|
||||
_IN_
|
||||
</port>
|
||||
</input>
|
||||
<output>
|
||||
<port id="2">
|
||||
_OUT_
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
</layers>
|
||||
<edges>
|
||||
<edge from-layer="1" from-port="1" to-layer="2" to-port="1"/>
|
||||
</edges>
|
||||
</net>
|
||||
)V0G0N";
|
||||
|
||||
std::string getModel(depth_to_space_test_params p) {
|
||||
std::string model = model_t;
|
||||
std::string in_shape, out_shape;
|
||||
|
||||
for (size_t i = 0; i < p.out_shape.size(); i++) {
|
||||
in_shape += "<dim>";
|
||||
in_shape += std::to_string(p.out_shape[i]) + "</dim>\n";
|
||||
}
|
||||
for (size_t i = 0; i < p.in_shape.size(); i++) {
|
||||
out_shape += "<dim>";
|
||||
out_shape += std::to_string(p.in_shape[i]) + "</dim>\n";
|
||||
}
|
||||
REPLACE_WITH_STR(model, "_IN_", in_shape);
|
||||
REPLACE_WITH_STR(model, "_OUT_", out_shape);
|
||||
REPLACE_WITH_NUM(model, "_BS_", p.block_size);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void TearDown() {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
try {
|
||||
TestsCommon::SetUp();
|
||||
depth_to_space_test_params p = ::testing::WithParamInterface<depth_to_space_test_params>::GetParam();
|
||||
std::string model = getModel(p);
|
||||
//std::cout << model;
|
||||
InferenceEngine::Core core;
|
||||
InferenceEngine::CNNNetwork network;
|
||||
ASSERT_NO_THROW(network = core.ReadNetwork(model, InferenceEngine::Blob::CPtr()));
|
||||
|
||||
MKLDNNGraphTestClass graph;
|
||||
graph.CreateGraph(network);
|
||||
|
||||
// Output Data
|
||||
InferenceEngine::OutputsDataMap out;
|
||||
out = network.getOutputsInfo();
|
||||
InferenceEngine::BlobMap outputBlobs;
|
||||
|
||||
std::pair<std::string, InferenceEngine::DataPtr> item = *out.begin();
|
||||
|
||||
InferenceEngine::TBlob<float>::Ptr output;
|
||||
output = InferenceEngine::make_shared_blob<float>(item.second->getTensorDesc());
|
||||
output->allocate();
|
||||
outputBlobs[item.first] = output;
|
||||
|
||||
// Output Reference
|
||||
InferenceEngine::TBlob<float> dst_ref(item.second->getTensorDesc());
|
||||
dst_ref.allocate();
|
||||
|
||||
// Input Data
|
||||
InferenceEngine::Blob::Ptr src;
|
||||
src = InferenceEngine::make_shared_blob<float>({ InferenceEngine::Precision::FP32, p.out_shape, InferenceEngine::TensorDesc::getLayoutByDims(p.out_shape) });
|
||||
src->allocate();
|
||||
if (p.reference.size())
|
||||
memcpy(static_cast<float*>(src->buffer()), &p.reference[0], sizeof(float)*p.reference.size());
|
||||
auto * srcPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(src.get());
|
||||
if (srcPtr == nullptr)
|
||||
FAIL() << "Cannot cast blob to TBlob<float>.";
|
||||
|
||||
// Check results
|
||||
InferenceEngine::SizeVector out_dims;
|
||||
ref_space_to_depth(*srcPtr, dst_ref, p.block_size);
|
||||
|
||||
// Check results
|
||||
if (p.reference.size()) {
|
||||
// fill_data_dbgval(src->buffer(), src->size());
|
||||
// if (memcmp(dst_ref.data(), &p.reference[0], p.reference.size() * sizeof(float)) != 0)
|
||||
// FAIL() << "Wrong result with compare TF reference!";
|
||||
}
|
||||
|
||||
InferenceEngine::BlobMap srcs;
|
||||
srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("input", src));
|
||||
|
||||
// Infer
|
||||
graph.Infer(srcs, outputBlobs);
|
||||
compare(*output, dst_ref);
|
||||
}
|
||||
catch (const InferenceEngine::details::InferenceEngineException &e) {
|
||||
FAIL() << e.what();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
class MKLDNNCPUExtDepthToSpaceToDepthTests : public TestsCommon, public WithParamInterface<depth_to_space_test_params> {
|
||||
std::string model_t = R"V0G0N(
|
||||
<net Name="DepthToSpaceToDepth_net" version="2" precision="FP32" batch="1">
|
||||
<layers>
|
||||
<layer name="input" type="Input" precision="FP32" id="1">
|
||||
<output>
|
||||
<port id="1">
|
||||
_IN_
|
||||
</port>
|
||||
</output>s
|
||||
</layer>
|
||||
<layer name="intermediate" id="2" type="DepthToSpace" precision="FP32">
|
||||
<data block_size="_BS_"/>
|
||||
<input>
|
||||
<port id="1">
|
||||
_IN_
|
||||
</port>
|
||||
</input>
|
||||
<output>
|
||||
<port id="2">
|
||||
_OUT_
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
<layer name="output" id="3" type="SpaceToDepth" precision="FP32">
|
||||
<data block_size="_BS_"/>
|
||||
<input>
|
||||
<port id="1">
|
||||
_OUT_
|
||||
</port>
|
||||
</input>
|
||||
<output>
|
||||
<port id="2">
|
||||
_IN_
|
||||
</port>
|
||||
</output>
|
||||
</layer>
|
||||
</layers>
|
||||
<edges>
|
||||
<edge from-layer="1" from-port="1" to-layer="2" to-port="1"/>
|
||||
<edge from-layer="2" from-port="2" to-layer="3" to-port="1"/>
|
||||
</edges>
|
||||
</net>
|
||||
)V0G0N";
|
||||
|
||||
std::string getModel(depth_to_space_test_params p) {
|
||||
std::string model = model_t;
|
||||
std::string in_shape, out_shape;
|
||||
|
||||
for (size_t i = 0; i < p.in_shape.size(); i++) {
|
||||
in_shape += "<dim>";
|
||||
in_shape += std::to_string(p.in_shape[i]) + "</dim>\n";
|
||||
}
|
||||
for (size_t i = 0; i < p.out_shape.size(); i++) {
|
||||
out_shape += "<dim>";
|
||||
out_shape += std::to_string(p.out_shape[i]) + "</dim>\n";
|
||||
}
|
||||
REPLACE_WITH_STR(model, "_IN_", in_shape);
|
||||
REPLACE_WITH_STR(model, "_OUT_", out_shape);
|
||||
REPLACE_WITH_NUM(model, "_BS_", p.block_size);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void TearDown() {
|
||||
}
|
||||
|
||||
virtual void SetUp() {
|
||||
try {
|
||||
TestsCommon::SetUp();
|
||||
depth_to_space_test_params p = ::testing::WithParamInterface<depth_to_space_test_params>::GetParam();
|
||||
std::string model = getModel(p);
|
||||
|
||||
InferenceEngine::Core core;
|
||||
InferenceEngine::CNNNetwork network;
|
||||
ASSERT_NO_THROW(network = core.ReadNetwork(model, InferenceEngine::Blob::CPtr()));
|
||||
|
||||
MKLDNNGraphTestClass graph;
|
||||
graph.CreateGraph(network);
|
||||
|
||||
// Output Data
|
||||
InferenceEngine::OutputsDataMap out;
|
||||
out = network.getOutputsInfo();
|
||||
InferenceEngine::BlobMap outputBlobs;
|
||||
|
||||
std::pair<std::string, InferenceEngine::DataPtr> item = *out.begin();
|
||||
|
||||
InferenceEngine::TBlob<float>::Ptr output;
|
||||
output = InferenceEngine::make_shared_blob<float>(item.second->getTensorDesc());
|
||||
output->allocate();
|
||||
outputBlobs[item.first] = output;
|
||||
|
||||
// Input Data
|
||||
InferenceEngine::Blob::Ptr src;
|
||||
src = InferenceEngine::make_shared_blob<float>({ InferenceEngine::Precision::FP32, p.in_shape, InferenceEngine::TensorDesc::getLayoutByDims(p.in_shape) });
|
||||
src->allocate();
|
||||
fill_data_dbgval(src->buffer(), src->size());
|
||||
auto * srcPtr = dynamic_cast<InferenceEngine::TBlob<float>*>(src.get());
|
||||
if (srcPtr == nullptr)
|
||||
FAIL() << "Cannot cast blob to TBlob<float>.";
|
||||
|
||||
InferenceEngine::BlobMap srcs;
|
||||
srcs.insert(std::pair<std::string, InferenceEngine::Blob::Ptr>("input", src));
|
||||
|
||||
// Infer
|
||||
graph.Infer(srcs, outputBlobs);
|
||||
compare(*output, *src);
|
||||
}
|
||||
catch (const InferenceEngine::details::InferenceEngineException &e) {
|
||||
FAIL() << e.what();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(MKLDNNCPUExtDepthToSpaceTests, TestsDepthToSpace) {}
|
||||
// Test data vectors
|
||||
static std::vector<float> test0 = { 0.f, 6.f, 1.f, 7.f, 2.f, 8.f, 12.f, 18.f, 13.f, 19.f, 14.f, 20.f, 3.f, 9.f, 4.f, 10.f, 5.f, 11.f, 15.f, 21.f, 16.f, 22.f, 17.f, 23.f};
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestsDepthToSpace, MKLDNNCPUExtDepthToSpaceTests,
|
||||
::testing::Values(
|
||||
// Params: in_shape, block_size, out_shape, reference
|
||||
depth_to_space_test_params{ { 1, 4, 2, 3 }, 2, { 1, 1, 4, 6 }, test0 },
|
||||
depth_to_space_test_params{ { 4, 2, 3 }, 2, { 1, 1, 4, 6 }, test0 },
|
||||
depth_to_space_test_params{ { 1, 4, 2, 3 }, 2, { 4, 6 }, test0 },
|
||||
depth_to_space_test_params{ { 4, 2, 3 }, 2, { 4, 6 }, test0 },
|
||||
depth_to_space_test_params{ { 5, 4, 2, 3 }, 2, { 5, 1, 4, 6 }, test0 },
|
||||
depth_to_space_test_params{ { 2, 3, 5, 4, 2, 3 }, 2, { 2, 3, 5, 1, 4, 6 }, test0 }
|
||||
));
|
||||
|
||||
|
||||
TEST_P(MKLDNNCPUExtDepthToSpaceToDepthTests, TestsDepthToSpaceToDepth) {}
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
TestsDepthToSpaceToDepth, MKLDNNCPUExtDepthToSpaceToDepthTests,
|
||||
::testing::Values(
|
||||
// Params: in_shape, block_size, out_shape, reference
|
||||
depth_to_space_test_params{ { 1, 9, 2, 3 }, 3,{ 1, 1, 6, 9 },{} },
|
||||
depth_to_space_test_params{ { 16, 2, 3 }, 4,{ 1, 1, 8, 12 },{} },
|
||||
depth_to_space_test_params{ { 1, 25, 4, 3 }, 5,{ 20, 15 },{} },
|
||||
depth_to_space_test_params{ { 72, 10, 3 }, 6,{ 2, 60, 18 },{} },
|
||||
depth_to_space_test_params{ { 5, 8, 2, 3 }, 2,{ 5, 2, 4, 6 },{} },
|
||||
depth_to_space_test_params{ { 2, 3, 5, 16, 2, 3 }, 2,{ 2, 3, 5, 4, 4, 6 },{} }
|
||||
));
|
Loading…
Reference in New Issue
Block a user