std::make_shared<Builder::NodeConverter<::ngraph::op::v1::LogicalNot>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::ReduceLogicalAnd>>(),
std::make_shared<Builder::NodeConverter<::ngraph::op::v1::ReduceLogicalOr>>(),
+ std::make_shared<Builder::NodeConverter<::ngraph::op::ShuffleChannels>>(),
};
CNNLayerPtr result;
}
template <>
+CNNLayer::Ptr NodeConverter<ngraph::op::ShuffleChannels>::createLayer(const std::shared_ptr<ngraph::Node>& layer) const {
+ LayerParams params = {layer->get_friendly_name(), "ShuffleChannels", details::convertPrecision(layer->get_output_element_type(0))};
+
+ auto res = std::make_shared<InferenceEngine::ShuffleChannelsLayer>(params);
+ auto castedLayer = ngraph::as_type_ptr<ngraph::op::ShuffleChannels>(layer);
+ if (castedLayer == nullptr) THROW_IE_EXCEPTION << "Cannot get " << params.type << " layer " << params.name;
+
+ res->params["axis"] = std::to_string(castedLayer->get_axis());
+ res->params["group"] = std::to_string(castedLayer->get_group());
+
+ return res;
+}
+
+template <>
CNNLayer::Ptr NodeConverter<ngraph::op::DetectionOutput>::createLayer(
const std::shared_ptr<ngraph::Node>& layer) const {
LayerParams params = {layer->get_friendly_name(), "DetectionOutput",
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) ||
- std::dynamic_pointer_cast<const ::ngraph::opset3::ShuffleChannels>(node);
+ std::dynamic_pointer_cast<const ::ngraph::opset2::SpaceToBatch>(node);
};
auto nGraphFunc = clonedNetwork->getFunction();
// Disable shape inference (WA for generic operations)
#include <cmath>
#include <string>
#include <vector>
+#include <set>
#include <cassert>
#include "ie_parallel.hpp"
if (src_dims.size() != dst_dims.size())
THROW_IE_EXCEPTION << layer->name << " Incorrect number of input/output dimensions!";
- if (layer->insData[0].lock()->getTensorDesc().getPrecision() != Precision::FP32)
- THROW_IE_EXCEPTION << layer->name << " Incorrect input precision. Only F32 is supported!";
-
- if (layer->outData[0]->getTensorDesc().getPrecision() != Precision::FP32)
- THROW_IE_EXCEPTION << layer->name << " Incorrect output precision. Only F32 is supported!";
+ const auto precision = layer->insData[0].lock()->getTensorDesc().getPrecision();
+ if (_supported_precisions_sizes.find(precision.size()) == _supported_precisions_sizes.end())
+ THROW_IE_EXCEPTION << layer->name << "has unsupported precision: " << precision.name();
int axis = layer->GetParamAsInt("axis", 1);
if (axis < 0)
ownStrides[2] = own_dims[1];
work_amount_dst = ownStrides[0] * own_dims[0];
- addConfig(layer, { DataConfigurator(ConfLayout::PLN) }, { DataConfigurator(ConfLayout::PLN) });
+ LayerConfig config;
+ DataConfig inConfig;
+ inConfig.desc = layer->insData[0].lock()->getTensorDesc();
+
+ config.inConfs.push_back(inConfig);
+
+ DataConfig outConfig;
+ outConfig.desc = layer->outData[0]->getTensorDesc();
+ outConfig.desc.setPrecision(inConfig.desc.getPrecision());
+ outConfig.desc.setLayout(inConfig.desc.getLayout());
+ 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: {
+ process_data<PrecisionTrait<Precision::U8>::value_type>(inputs, outputs);
+ break;
+ }
+ case 2: {
+ process_data<PrecisionTrait<Precision::U16>::value_type>(inputs, outputs);
+ break;
+ }
+ case 4: {
+ process_data<PrecisionTrait<Precision::I32>::value_type>(inputs, outputs);
+ break;
+ }
+ case 8: {
+ process_data<PrecisionTrait<Precision::U64>::value_type>(inputs, outputs);
+ break;
+ }
+ default: {
+ if (resp) {
+ std::string errorMsg = "ShuffleChannels 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 process_data(std::vector<Blob::Ptr>& inputs, std::vector<Blob::Ptr>& outputs) noexcept {
+ const T* src_data = inputs[0]->cbuffer().as<const T*>() +
+ inputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
+ T* dst_data = outputs[0]->cbuffer().as<T*>() +
+ outputs[0]->getTensorDesc().getBlockingDesc().getOffsetPadding();
if (dataLength > 1) {
// Vectorized & Parallel
splitter(work_amount_dst, nthr, ithr, start, end);
src_idx = initter(start, CNTR_SIZE, counters, own_dims, ownStrides);
for (size_t iwork = start, dst_idx = start * dataLength; iwork < end; ++iwork, dst_idx += dataLength) {
- memcpy(&dst_data[dst_idx], &src_data[dataLength * src_idx], sizeof(float) * dataLength);
+ memcpy(&dst_data[dst_idx], &src_data[dataLength * src_idx], sizeof(T) * dataLength);
src_idx = updater(src_idx, CNTR_SIZE, counters, own_dims, ownStrides);
}
});
}
});
}
-
- return OK;
}
private:
size_t work_amount_dst;
size_t own_dims[CNTR_SIZE];
size_t ownStrides[CNTR_SIZE];
+
+ static const std::set<size_t> _supported_precisions_sizes;
};
+const std::set<size_t> ShuffleChannelsImpl::_supported_precisions_sizes = {1, 2, 4, 8};
+
REG_FACTORY_FOR(ShuffleChannelsImpl, ShuffleChannels);
} // namespace Cpu
#include <transformations_visibility.hpp>
#include <ngraph/pass/graph_rewrite.hpp>
+#include "transformations/utils/pass_param.hpp"
namespace ngraph {
namespace pass {
} // namespace pass
} // namespace ngraph
-class ngraph::pass::ConvertShuffleChannels3: public ngraph::pass::GraphRewrite {
+class ngraph::pass::ConvertShuffleChannels3: public ngraph::pass::GraphRewrite, public ngraph::pass::PassParam {
public:
ConvertShuffleChannels3() : GraphRewrite() {
convert_shuffle_channels3();
auto input = std::make_shared<pattern::op::Label>(element::f32, Shape{1, 1, 1, 1});
auto shuffle_channels = std::make_shared<::opset3::ShuffleChannels>(input);
- ngraph::graph_rewrite_callback callback = [](pattern::Matcher &m) {
+ ngraph::graph_rewrite_callback callback = [this](pattern::Matcher &m) {
auto shuffle_channels = std::dynamic_pointer_cast<::opset3::ShuffleChannels>(m.get_match_root());
- if (!shuffle_channels) {
+ if (!shuffle_channels || transformation_callback(shuffle_channels)) {
return false;
}
if (shuffle_channels->input_value(0).get_partial_shape().rank().is_dynamic()) {
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <vector>
+
+#include "single_layer_tests/shuffle_channels.hpp"
+
+using namespace LayerTestsDefinitions;
+
+namespace {
+
+const std::vector<InferenceEngine::Precision> netPrecisions = {
+ InferenceEngine::Precision::I8,
+ InferenceEngine::Precision::U8,
+ InferenceEngine::Precision::I16,
+ InferenceEngine::Precision::I32,
+ InferenceEngine::Precision::FP32
+};
+
+const std::vector<int> axes = {0, 1, 2, 3};
+const std::vector<int> negativeAxes = {-4, -3, -2, -1};
+const std::vector<int> groups = {1, 2, 3};
+
+const auto shuffleChannelsParams4D = ::testing::Combine(
+ ::testing::ValuesIn(axes),
+ ::testing::ValuesIn(groups)
+);
+
+const auto shuffleChannelsParamsNegativeAxis4D = ::testing::Combine(
+ ::testing::ValuesIn(negativeAxes),
+ ::testing::ValuesIn(groups)
+);
+
+INSTANTIATE_TEST_CASE_P(ShuffleChannels4D, ShuffleChannelsLayerTest,
+ ::testing::Combine(
+ shuffleChannelsParams4D,
+ ::testing::ValuesIn(netPrecisions),
+ ::testing::Values(std::vector<size_t >({6, 6, 6, 6})),
+ ::testing::Values(CommonTestUtils::DEVICE_CPU)),
+ ShuffleChannelsLayerTest::getTestCaseName);
+
+INSTANTIATE_TEST_CASE_P(ShuffleChannelsNegativeAxis4D, ShuffleChannelsLayerTest,
+ ::testing::Combine(
+ shuffleChannelsParamsNegativeAxis4D,
+ ::testing::ValuesIn(netPrecisions),
+ ::testing::Values(std::vector<size_t >({6, 6, 6, 6})),
+ ::testing::Values(CommonTestUtils::DEVICE_CPU)),
+ ShuffleChannelsLayerTest::getTestCaseName);
+
+} // namespace
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#pragma once
+
+#include <tuple>
+#include <vector>
+#include <string>
+#include <memory>
+
+#include "functional_test_utils/layer_test_utils.hpp"
+
+typedef std::tuple<
+ int, // axis
+ int // group
+> shuffleChannelsSpecificParams;
+typedef std::tuple<
+ shuffleChannelsSpecificParams,
+ InferenceEngine::Precision, // Net precision
+ InferenceEngine::SizeVector, // Input shapes
+ LayerTestsUtils::TargetDevice // Device name
+> shuffleChannelsLayerTestParamsSet;
+namespace LayerTestsDefinitions {
+
+
+class ShuffleChannelsLayerTest : public testing::WithParamInterface<shuffleChannelsLayerTestParamsSet>,
+ public LayerTestsUtils::LayerTestsCommon {
+public:
+ static std::string getTestCaseName(testing::TestParamInfo<shuffleChannelsLayerTestParamsSet> obj);
+
+protected:
+ void SetUp() override;
+};
+
+} // namespace LayerTestsDefinitions
--- /dev/null
+// Copyright (C) 2020 Intel Corporation
+// SPDX-License-Identifier: Apache-2.0
+//
+
+#include <tuple>
+#include <vector>
+#include <string>
+#include <memory>
+#include <functional>
+
+#include "single_layer_tests/shuffle_channels.hpp"
+#include "ngraph_functions/builders.hpp"
+
+namespace LayerTestsDefinitions {
+
+std::string ShuffleChannelsLayerTest::getTestCaseName(testing::TestParamInfo<shuffleChannelsLayerTestParamsSet> obj) {
+ shuffleChannelsSpecificParams shuffleChannelsParams;
+ InferenceEngine::Precision netPrecision;
+ InferenceEngine::SizeVector inputShapes;
+ std::string targetDevice;
+ std::tie(shuffleChannelsParams, netPrecision, inputShapes, targetDevice) = obj.param;
+ int axis, group;
+ std::tie(axis, group) = shuffleChannelsParams;
+
+ std::ostringstream result;
+ result << "IS=" << CommonTestUtils::vec2str(inputShapes) << "_";
+ result << "Axis=" << std::to_string(axis) << "_";
+ result << "Group=" << std::to_string(group) << "_";
+ result << "netPRC=" << netPrecision.name() << "_";
+ result << "targetDevice=" << targetDevice;
+ return result.str();
+}
+
+void ShuffleChannelsLayerTest::SetUp() {
+ shuffleChannelsSpecificParams shuffleChannelsParams;
+ std::vector<size_t> inputShape;
+ auto netPrecision = InferenceEngine::Precision::UNSPECIFIED;
+ std::tie(shuffleChannelsParams, netPrecision, inputShape, targetDevice) = this->GetParam();
+ int axis, group;
+ std::tie(axis, group) = shuffleChannelsParams;
+ auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
+ auto params = ngraph::builder::makeParams(ngPrc, {inputShape});
+ auto paramOuts = ngraph::helpers::convert2OutputVector(
+ ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(params));
+ auto shuffleChannels = std::dynamic_pointer_cast<ngraph::opset3::ShuffleChannels>(
+ ngraph::builder::makeShuffleChannels(paramOuts[0], axis, group));
+ ngraph::ResultVector results{std::make_shared<ngraph::opset3::Result>(shuffleChannels)};
+ function = std::make_shared<ngraph::Function>(results, params, "shuffleChannels");
+}
+
+TEST_P(ShuffleChannelsLayerTest, CompareWithRefs) {
+ Run();
+}
+} // namespace LayerTestsDefinitions
ngraph::opset3::SpaceToDepth::SpaceToDepthMode mode,
size_t blockSize);
+std::shared_ptr<Node> makeShuffleChannels(const ngraph::Output<Node> &in,
+ int axis,
+ int group);
+
} // namespace builder
} // namespace ngraph
--- /dev/null
+// 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> makeShuffleChannels(const ngraph::Output<Node> &in,
+ int axis,
+ int group) {
+ return std::make_shared<ngraph::opset3::ShuffleChannels>(in, axis, group);
+}
+
+} // namespace builder
+} // namespace ngraph
\ No newline at end of file