Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
84bc851ecf
18
.github/org_control/check_pr.py
vendored
18
.github/org_control/check_pr.py
vendored
@ -147,21 +147,29 @@ def get_wrong_commits(pull):
|
||||
# import pprint; pprint.pprint(commit.raw_data)
|
||||
print("Commit SHA:", commit.sha)
|
||||
# Use raw data because commit author can be non GitHub user
|
||||
commit_email = (commit.raw_data["commit"]["author"]["email"] or "").lower()
|
||||
print(" Commit email:", commit_email)
|
||||
commit_author_email = (commit.raw_data["commit"]["author"]["email"] or "").lower()
|
||||
commit_committer_email = (commit.raw_data["commit"]["committer"]["email"] or "").lower()
|
||||
print(" Commit author email:", commit_author_email)
|
||||
print(" Commit committer email:", commit_committer_email)
|
||||
if not github_api.is_valid_user(commit.author):
|
||||
print(
|
||||
" ERROR: User with the commit email is absent in GitHub:",
|
||||
" ERROR: User with the commit author email is absent in GitHub:",
|
||||
commit.raw_data["commit"]["author"]["name"],
|
||||
)
|
||||
wrong_commits.add(commit.sha)
|
||||
if not github_api.is_valid_user(commit.committer):
|
||||
print(
|
||||
" ERROR: User with the commit committer email is absent in GitHub:",
|
||||
commit.raw_data["commit"]["committer"]["name"],
|
||||
)
|
||||
wrong_commits.add(commit.sha)
|
||||
if not commit.raw_data["commit"]["verification"]["verified"]:
|
||||
print(
|
||||
" WARNING: The commit is not verified. Reason:",
|
||||
commit.raw_data["commit"]["verification"]["reason"],
|
||||
)
|
||||
if pr_author_email != commit_email:
|
||||
print(" WARNING: Commit email and GitHub PR author public email are differnt")
|
||||
if pr_author_email != commit_author_email or pr_author_email != commit_committer_email:
|
||||
print(" WARNING: Commit emails and GitHub PR author public email are differnt")
|
||||
return wrong_commits
|
||||
|
||||
|
||||
|
@ -277,8 +277,8 @@ int main(int argc, char* argv[]) {
|
||||
setThroughputStreams();
|
||||
|
||||
if ((device_name.find("MULTI") != std::string::npos) && (device_name.find("CPU") != std::string::npos)) {
|
||||
slog::warn << "Turn on GPU trottling. Multi-device execution with "
|
||||
"the CPU + GPU performs best with GPU trottling hint,"
|
||||
slog::warn << "Turn on GPU throttling. Multi-device execution with "
|
||||
"the CPU + GPU performs best with GPU throttling hint, "
|
||||
<< "which releases another CPU thread (that is otherwise "
|
||||
"used by the GPU driver for active polling)"
|
||||
<< slog::endl;
|
||||
|
@ -120,10 +120,10 @@ bool NormalizeL2Transformation::transform(TransformationContext &context, ngraph
|
||||
}
|
||||
|
||||
auto newNormalize = std::make_shared<op::TypeRelaxed<opset1::NormalizeL2>>(
|
||||
std::vector<ngraph::element::Type>{ element::f32, element::f32 },
|
||||
std::vector<ngraph::element::Type>{ element::f32, axes->output(0).get_element_type() },
|
||||
std::vector<ngraph::element::Type>{deqPrecision},
|
||||
ngraph::op::TemporaryReplaceOutputType(dequantization.subtract == nullptr ? dequantization.data : dequantization.subtract, element::f32).get(),
|
||||
ngraph::op::TemporaryReplaceOutputType(axes->clone_with_new_inputs({}), element::f32).get(),
|
||||
axes,
|
||||
normalize->get_eps(),
|
||||
normalize->get_eps_mode());
|
||||
NetworkHelper::copyInfo(normalize, newNormalize);
|
||||
|
@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "shared_test_classes/single_layer/space_to_batch.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST_P(SpaceToBatchLayerTest, Serialize) {
|
||||
Serialize();
|
||||
}
|
||||
|
||||
const std::vector<std::vector<int64_t>> blockShapes4D{{1, 1, 2, 2}};
|
||||
const std::vector<std::vector<int64_t>> padsBegins4D{{0, 0, 0, 0},
|
||||
{0, 0, 0, 2}};
|
||||
const std::vector<std::vector<int64_t>> padsEnds4D{{0, 0, 0, 0}, {0, 0, 0, 2}};
|
||||
const std::vector<std::vector<size_t>> dataShapes4D{
|
||||
{1, 1, 2, 2}, {1, 3, 2, 2}, {1, 1, 4, 4}, {2, 1, 2, 4}};
|
||||
|
||||
const auto SpaceToBatch4D = ::testing::Combine(
|
||||
::testing::ValuesIn(blockShapes4D), ::testing::ValuesIn(padsBegins4D),
|
||||
::testing::ValuesIn(padsEnds4D), ::testing::ValuesIn(dataShapes4D),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Layout::ANY),
|
||||
::testing::Values(InferenceEngine::Layout::ANY),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU));
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(smoke_spacetobatch4D_Serialization,
|
||||
SpaceToBatchLayerTest, SpaceToBatch4D,
|
||||
SpaceToBatchLayerTest::getTestCaseName);
|
||||
|
||||
} // namespace
|
@ -30,7 +30,7 @@ TEST(TransformationTests, MVNFusionTestOutside) {
|
||||
auto sub2 = std::make_shared<ngraph::opset6::Subtract>(input, mean2);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub2, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto const_0_5 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 0.5 });
|
||||
auto power_sqrt = std::make_shared<ngraph::opset6::Power>(mean3, const_0_5);
|
||||
@ -70,7 +70,7 @@ TEST(TransformationTests, MVNFusionTestReuseSub) {
|
||||
auto sub1 = std::make_shared<ngraph::opset6::Subtract>(input, mean1);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub1, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto const_0_5 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 0.5 });
|
||||
auto power_sqrt = std::make_shared<ngraph::opset6::Power>(mean3, const_0_5);
|
||||
@ -111,7 +111,7 @@ TEST(TransformationTests, MVNFusionTestWithConvert) {
|
||||
auto cast = std::make_shared<ngraph::opset6::Convert>(sub1, ngraph::element::f32);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(cast, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto const_0_5 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 0.5 });
|
||||
auto power_sqrt = std::make_shared<ngraph::opset6::Power>(mean3, const_0_5);
|
||||
@ -151,7 +151,7 @@ TEST(TransformationTests, MVNFusionTestSqrt) {
|
||||
auto sub1 = std::make_shared<ngraph::opset6::Subtract>(input, mean1);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub1, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto power_sqrt = std::make_shared<ngraph::opset6::Sqrt>(mean3);
|
||||
auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 });
|
||||
@ -190,7 +190,7 @@ TEST(TransformationTests, MVNFusionTestAltDiv) {
|
||||
auto sub1 = std::make_shared<ngraph::opset6::Subtract>(input, mean1);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub1, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto const_0_5 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 0.5 });
|
||||
auto power_sqrt = std::make_shared<ngraph::opset6::Power>(mean3, const_0_5);
|
||||
@ -231,7 +231,7 @@ TEST(TransformationTests, MVNFusionTestInsideSqrt) {
|
||||
auto sub2 = std::make_shared<ngraph::opset6::Subtract>(input, mean2);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub2, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 });
|
||||
auto add_eps = std::make_shared<ngraph::opset6::Add>(mean3, eps);
|
||||
@ -271,7 +271,7 @@ TEST(TransformationTests, MVNFusionTestReuseSubInsideSqrt) {
|
||||
auto sub1 = std::make_shared<ngraph::opset6::Subtract>(input, mean1);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub1, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 });
|
||||
auto add_eps = std::make_shared<ngraph::opset6::Add>(mean3, eps);
|
||||
@ -312,7 +312,7 @@ TEST(TransformationTests, MVNFusionTestWithConvertInsideSqrt) {
|
||||
auto cast = std::make_shared<ngraph::opset6::Convert>(sub1, ngraph::element::f32);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(cast, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 });
|
||||
auto add_eps = std::make_shared<ngraph::opset6::Add>(mean3, eps);
|
||||
@ -352,7 +352,7 @@ TEST(TransformationTests, MVNFusionTestSqrtInsideSqrt) {
|
||||
auto sub1 = std::make_shared<ngraph::opset6::Subtract>(input, mean1);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub1, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 });
|
||||
auto add_eps = std::make_shared<ngraph::opset6::Add>(mean3, eps);
|
||||
@ -391,7 +391,7 @@ TEST(TransformationTests, MVNFusionTestAltDivInsideSqrt) {
|
||||
auto sub1 = std::make_shared<ngraph::opset6::Subtract>(input, mean1);
|
||||
auto const_2 = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 2 });
|
||||
auto power_sqr = std::make_shared<ngraph::opset6::Power>(sub1, const_2);
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3_axes = ngraph::opset6::Constant::create(ngraph::element::i32, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
auto mean3 = std::make_shared<ngraph::opset6::ReduceMean>(power_sqr, mean3_axes);
|
||||
auto eps = ngraph::opset6::Constant::create(ngraph::element::f32, ngraph::Shape{}, { 1e-9 });
|
||||
auto add_eps = std::make_shared<ngraph::opset6::Add>(mean3, eps);
|
||||
|
@ -11,47 +11,64 @@ using namespace LayerTestsDefinitions;
|
||||
|
||||
namespace {
|
||||
|
||||
spaceToBatchParamsTuple stb_only_test_cases[] = {
|
||||
spaceToBatchParamsTuple({1, 1, 2, 2}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 1, 2, 2},
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Layout::ANY,
|
||||
InferenceEngine::Layout::ANY,
|
||||
CommonTestUtils::DEVICE_CPU),
|
||||
spaceToBatchParamsTuple({1, 1, 2, 2}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 3, 2, 2},
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Layout::ANY,
|
||||
InferenceEngine::Layout::ANY,
|
||||
CommonTestUtils::DEVICE_CPU),
|
||||
spaceToBatchParamsTuple({1, 1, 2, 2}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 1, 4, 4},
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Layout::ANY,
|
||||
InferenceEngine::Layout::ANY,
|
||||
CommonTestUtils::DEVICE_CPU),
|
||||
spaceToBatchParamsTuple({1, 1, 2, 2}, {0, 0, 0, 2}, {0, 0, 0, 0}, {2, 1, 2, 4},
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Layout::ANY,
|
||||
InferenceEngine::Layout::ANY,
|
||||
CommonTestUtils::DEVICE_CPU),
|
||||
spaceToBatchParamsTuple({1, 1, 3, 2, 2}, {0, 0, 1, 0, 3}, {0, 0, 2, 0, 0}, {1, 1, 3, 2, 1},
|
||||
InferenceEngine::Precision::FP32,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Precision::UNSPECIFIED,
|
||||
InferenceEngine::Layout::ANY,
|
||||
InferenceEngine::Layout::ANY,
|
||||
CommonTestUtils::DEVICE_CPU),
|
||||
const std::vector<std::vector<int64_t >> blockShapes4D {
|
||||
{1, 1, 2, 2}
|
||||
};
|
||||
const std::vector<std::vector<int64_t >> padsBegins4D {
|
||||
{0, 0, 0, 0}, {0, 0, 0, 2}
|
||||
};
|
||||
const std::vector<std::vector<int64_t >> padsEnds4D {
|
||||
{0, 0, 0, 0}, {0, 0, 0, 2}
|
||||
};
|
||||
const std::vector<std::vector<size_t >> dataShapes4D {
|
||||
{1, 1, 2, 2}, {1, 3, 2, 2}, {1, 1, 4, 4}, {2, 1, 2, 4}
|
||||
};
|
||||
|
||||
const auto SpaceToBatch4D = ::testing::Combine(
|
||||
::testing::ValuesIn(blockShapes4D),
|
||||
::testing::ValuesIn(padsBegins4D),
|
||||
::testing::ValuesIn(padsEnds4D),
|
||||
::testing::ValuesIn(dataShapes4D),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Layout::ANY),
|
||||
::testing::Values(InferenceEngine::Layout::ANY),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
smoke_MKLDNN, SpaceToBatchLayerTest, ::testing::ValuesIn(stb_only_test_cases),
|
||||
smoke_spacetobatch4D, SpaceToBatchLayerTest, SpaceToBatch4D,
|
||||
SpaceToBatchLayerTest::getTestCaseName);
|
||||
|
||||
const std::vector<std::vector<int64_t >> blockShapes5D {
|
||||
{1, 1, 3, 2, 2}
|
||||
};
|
||||
const std::vector<std::vector<int64_t >> padsBegins5D {
|
||||
{0, 0, 1, 0, 3}
|
||||
};
|
||||
const std::vector<std::vector<int64_t >> padsEnds5D {
|
||||
{0, 0, 2, 0, 0}
|
||||
};
|
||||
const std::vector<std::vector<size_t >> dataShapes5D {
|
||||
{1, 1, 3, 2, 1}
|
||||
};
|
||||
|
||||
const auto SpaceToBatch5D = ::testing::Combine(
|
||||
::testing::ValuesIn(blockShapes5D),
|
||||
::testing::ValuesIn(padsBegins5D),
|
||||
::testing::ValuesIn(padsEnds5D),
|
||||
::testing::ValuesIn(dataShapes5D),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Precision::FP32),
|
||||
::testing::Values(InferenceEngine::Layout::ANY),
|
||||
::testing::Values(InferenceEngine::Layout::ANY),
|
||||
::testing::Values(CommonTestUtils::DEVICE_CPU)
|
||||
);
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
smoke_spacetobatch5D, SpaceToBatchLayerTest, SpaceToBatch5D,
|
||||
SpaceToBatchLayerTest::getTestCaseName);
|
||||
|
||||
} // namespace
|
@ -36,7 +36,7 @@ std::shared_ptr<ngraph::Function> NormalizeL2Function::getOriginal(
|
||||
|
||||
fakeQuantize->set_friendly_name("fakeQuantize");
|
||||
|
||||
const auto axesNode = std::make_shared<ngraph::op::Constant>(ngraph::element::u64, ngraph::Shape{ axes.size() }, axes);
|
||||
const auto axesNode = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{ axes.size() }, axes);
|
||||
axesNode->set_friendly_name("axes");
|
||||
const auto normalizeL2 = std::make_shared<ngraph::opset1::NormalizeL2>(fakeQuantize->output(0), axesNode, 1e-6, ngraph::op::EpsMode::ADD);
|
||||
normalizeL2->set_friendly_name("normalizeL2");
|
||||
@ -104,10 +104,10 @@ std::shared_ptr<ngraph::Function> NormalizeL2Function::getReference(
|
||||
|
||||
const auto axesNode = std::make_shared<ngraph::op::Constant>(ngraph::element::i64, ngraph::Shape{ axes.size() }, axes);
|
||||
const auto normalizeL2 = std::make_shared<ngraph::op::TypeRelaxed<ngraph::opset1::NormalizeL2>>(
|
||||
std::vector<ngraph::element::Type>{ element::f32, element::f32 },
|
||||
std::vector<ngraph::element::Type>{ element::f32, axesNode->output(0).get_element_type() },
|
||||
std::vector<ngraph::element::Type>{dequantizationAfter.empty() ? precision : element::f32},
|
||||
ngraph::op::TemporaryReplaceOutputType(deqBefore, element::f32).get(),
|
||||
ngraph::op::TemporaryReplaceOutputType(axesNode, element::f32).get(),
|
||||
axesNode,
|
||||
1e-6,
|
||||
epsMode);
|
||||
auto& rtInfo = normalizeL2->get_rt_info();
|
||||
|
@ -137,7 +137,7 @@ std::shared_ptr<Node> TransformationsAfterSplitFunction::getLayerByTransformatio
|
||||
}
|
||||
if (transformationName == "NormalizeL2Transformation") {
|
||||
const auto dequantization = makeDequantization(parent, { {element::f32}, {}, { 0.1f } });
|
||||
const auto axesNode = opset1::Constant::create(element::u64, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
const auto axesNode = opset1::Constant::create(element::i64, ngraph::Shape{ 3 }, { 1, 2, 3 });
|
||||
return std::make_shared<ngraph::opset1::NormalizeL2>(dequantization, axesNode, 1e-6, ngraph::op::EpsMode::ADD);
|
||||
}
|
||||
if (transformationName == "PReluTransformation") {
|
||||
|
@ -6,10 +6,6 @@
|
||||
|
||||
#include "ngraph/node.hpp"
|
||||
#include "ngraph/op/op.hpp"
|
||||
#include "ngraph/op/util/fused_op.hpp"
|
||||
|
||||
NGRAPH_SUPPRESS_DEPRECATED_START
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace op
|
||||
@ -17,12 +13,12 @@ namespace ngraph
|
||||
namespace v0
|
||||
{
|
||||
/// \brief Performs a SELU activation function on all elements of the input node
|
||||
class NGRAPH_API Selu : public ngraph::op::util::FusedOp
|
||||
class NGRAPH_API Selu : public ngraph::op::Op
|
||||
{
|
||||
public:
|
||||
static constexpr NodeTypeInfo type_info{"Selu", 0};
|
||||
const NodeTypeInfo& get_type_info() const override { return type_info; }
|
||||
Selu();
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
|
||||
Selu() = default;
|
||||
/// \brief Constructs a Selu node.
|
||||
///
|
||||
/// \param data - Node producing the input tensor
|
||||
@ -31,9 +27,10 @@ namespace ngraph
|
||||
Selu(const Output<Node>& data,
|
||||
const Output<Node>& alpha,
|
||||
const Output<Node>& lambda);
|
||||
virtual void pre_validate_and_infer_types() override;
|
||||
|
||||
void validate_and_infer_types() override;
|
||||
|
||||
bool visit_attributes(AttributeVisitor& visitor) override;
|
||||
virtual OutputVector decompose_op() const override;
|
||||
|
||||
virtual std::shared_ptr<Node>
|
||||
clone_with_new_inputs(const OutputVector& new_args) const override;
|
||||
@ -42,5 +39,3 @@ namespace ngraph
|
||||
using v0::Selu;
|
||||
} // namespace op
|
||||
} // namespace ngraph
|
||||
|
||||
NGRAPH_SUPPRESS_DEPRECATED_END
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/node.hpp"
|
||||
#include "ngraph/op/util/fused_op.hpp"
|
||||
#include "ngraph/op/op.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
@ -27,8 +26,8 @@ namespace ngraph
|
||||
class NGRAPH_API SpaceToBatch : public Op
|
||||
{
|
||||
public:
|
||||
static constexpr NodeTypeInfo type_info{"SpaceToBatch", 1};
|
||||
const NodeTypeInfo& get_type_info() const override { return type_info; }
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
|
||||
SpaceToBatch() = default;
|
||||
|
||||
/// \brief Constructs a SpaceToBatch operation.
|
||||
|
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/op/op.hpp"
|
||||
#include "ngraph/op/util/reduction_base.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
@ -15,7 +16,7 @@ namespace ngraph
|
||||
/// \brief Abstract base class for arithmetic reduction operations, i.e., operations
|
||||
/// where chosen axes of the input tensors are eliminated (reduced out) by
|
||||
/// repeated application of a particular binary arithmetic operation.
|
||||
class NGRAPH_API ArithmeticReduction : public Op
|
||||
class NGRAPH_API ArithmeticReduction : public ReductionBase
|
||||
{
|
||||
protected:
|
||||
/// \brief Constructs an arithmetic reduction operation.
|
||||
|
@ -2,6 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/axis_set.hpp"
|
||||
#include "ngraph/descriptor/tensor.hpp"
|
||||
#include "ngraph/util.hpp"
|
||||
@ -18,10 +20,5 @@ namespace ngraph
|
||||
/// \return Normalized (positive only) axes as an AxisSet object.
|
||||
AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor,
|
||||
const ngraph::Rank& rank,
|
||||
const std::string& node_description)
|
||||
{
|
||||
const auto axes_vector = host_tensor_2_vector<int64_t>(tensor);
|
||||
const auto normalized_axes = ngraph::normalize_axes(node_description, axes_vector, rank);
|
||||
return AxisSet{normalized_axes};
|
||||
}
|
||||
const std::string& node_description);
|
||||
} // namespace ngraph
|
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/op/op.hpp"
|
||||
#include "ngraph/op/util/reduction_base.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
@ -15,7 +16,7 @@ namespace ngraph
|
||||
/// \brief Abstract base class for logical reduction operations, i.e., operations where
|
||||
/// chosen axes of the input tensors are eliminated (reduced out) by repeated
|
||||
/// application of a particular binary logical operation.
|
||||
class NGRAPH_API LogicalReduction : public Op
|
||||
class NGRAPH_API LogicalReduction : public ReductionBase
|
||||
{
|
||||
protected:
|
||||
/// \brief Constructs a logical reduction operation.
|
||||
|
39
ngraph/core/include/ngraph/op/util/reduction_base.hpp
Normal file
39
ngraph/core/include/ngraph/op/util/reduction_base.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ngraph/op/op.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
namespace op
|
||||
{
|
||||
namespace util
|
||||
{
|
||||
class NGRAPH_API ReductionBase : public Op
|
||||
{
|
||||
protected:
|
||||
/// \brief Constructs a reduction operation.
|
||||
ReductionBase();
|
||||
|
||||
/// \brief Constructs a reduction operation.
|
||||
///
|
||||
/// \param arg Output that produces the first input tensor.
|
||||
/// \param reduction_axes The axis positions (0-based) to be eliminated.
|
||||
ReductionBase(const Output<Node>& arg, const Output<Node>& reduction_axes);
|
||||
|
||||
/// \brief Infers reduction operations output shape.
|
||||
///
|
||||
/// \param[in] keep_dims Reduction operation keeps dimensions.
|
||||
///
|
||||
/// \return Partial shape of the output.
|
||||
PartialShape infer_reduction_output_shape(const bool keep_dims);
|
||||
|
||||
public:
|
||||
NGRAPH_RTTI_DECLARATION;
|
||||
};
|
||||
} // namespace util
|
||||
} // namespace op
|
||||
} // namespace ngraph
|
@ -18,8 +18,6 @@
|
||||
#include "ngraph/runtime/reference/split.hpp"
|
||||
#include "ngraph/util.hpp"
|
||||
|
||||
// can't be removed currently due to arm-plugin dependency
|
||||
#include "ngraph/runtime/reference/convolution_backprop_data.hpp"
|
||||
namespace ngraph
|
||||
{
|
||||
namespace runtime
|
||||
@ -42,15 +40,18 @@ namespace ngraph
|
||||
std::vector<int> dilation;
|
||||
std::vector<int> pads_begin;
|
||||
std::vector<int> pads_end;
|
||||
std::vector<int> output_padding;
|
||||
|
||||
ConvolutionParams(const Strides& strides_,
|
||||
const Strides& dilation_,
|
||||
const CoordinateDiff& pads_begin_,
|
||||
const CoordinateDiff& pads_end_)
|
||||
const CoordinateDiff& pads_end_,
|
||||
const CoordinateDiff& output_padding_ = {0, 0, 0})
|
||||
: strides{strides_.begin(), strides_.end()}
|
||||
, dilation{dilation_.begin(), dilation_.end()}
|
||||
, pads_begin{pads_begin_.begin(), pads_begin_.end()}
|
||||
, pads_end{pads_end_.begin(), pads_end_.end()} {};
|
||||
, pads_end{pads_end_.begin(), pads_end_.end()}
|
||||
, output_padding{output_padding_.begin(), output_padding_.end()} {};
|
||||
};
|
||||
|
||||
template <typename Int>
|
||||
@ -86,15 +87,18 @@ namespace ngraph
|
||||
const size_t filter_channel_size = shape_size(filter_channel_shape);
|
||||
|
||||
for (int i_z = -p.pads_begin[0];
|
||||
i_z <= (p.pads_end[0] + input_size_z - dilated_filter_size_z);
|
||||
i_z <= (p.pads_end[0] + input_size_z - dilated_filter_size_z +
|
||||
p.output_padding[0]);
|
||||
i_z += p.strides[0])
|
||||
{
|
||||
for (int i_y = -p.pads_begin[1];
|
||||
i_y <= (p.pads_end[1] + input_size_y - dilated_filter_size_y);
|
||||
i_y <= (p.pads_end[1] + input_size_y - dilated_filter_size_y +
|
||||
p.output_padding[1]);
|
||||
i_y += p.strides[1])
|
||||
{
|
||||
for (int i_x = -p.pads_begin[2];
|
||||
i_x <= (p.pads_end[2] + input_size_x - dilated_filter_size_x);
|
||||
i_x <= (p.pads_end[2] + input_size_x - dilated_filter_size_x +
|
||||
p.output_padding[2]);
|
||||
i_x += p.strides[2])
|
||||
{
|
||||
auto input_channel = batch;
|
||||
@ -154,6 +158,8 @@ namespace ngraph
|
||||
std::prev(p.pads_begin.end(), spatial_rank), missing_dims, 0);
|
||||
p.pads_end.insert(
|
||||
std::prev(p.pads_end.end(), spatial_rank), missing_dims, 0);
|
||||
p.output_padding.insert(
|
||||
std::prev(p.output_padding.end(), spatial_rank), missing_dims, 0);
|
||||
in_shape.insert(std::next(in_shape.end(), -spatial_rank), missing_dims, 1);
|
||||
filter_shape.insert(
|
||||
std::prev(filter_shape.end(), spatial_rank), missing_dims, 1);
|
||||
@ -324,3 +330,6 @@ namespace ngraph
|
||||
} // namespace reference
|
||||
} // namespace runtime
|
||||
} // namespace ngraph
|
||||
|
||||
// can't be removed currently due to arm-plugin dependency
|
||||
#include "ngraph/runtime/reference/convolution_backprop_data.hpp"
|
||||
|
@ -10,11 +10,7 @@
|
||||
#include <numeric>
|
||||
|
||||
#include "ngraph/axis_vector.hpp"
|
||||
#include "ngraph/coordinate_transform.hpp"
|
||||
#include "ngraph/runtime/reference/concat.hpp"
|
||||
#include "ngraph/runtime/reference/helpers.hpp"
|
||||
#include "ngraph/runtime/reference/reverse.hpp"
|
||||
#include "ngraph/runtime/reference/split.hpp"
|
||||
#include "ngraph/runtime/reference/convolution.hpp"
|
||||
#include "ngraph/util.hpp"
|
||||
|
||||
namespace ngraph
|
||||
@ -23,217 +19,302 @@ namespace ngraph
|
||||
{
|
||||
namespace reference
|
||||
{
|
||||
// in: NC_I...
|
||||
// filter: C_OC_I...
|
||||
// out: NC_O...
|
||||
template <typename INPUT,
|
||||
typename FILTER,
|
||||
typename OUTPUT,
|
||||
typename ACCUMULATION = typename widen<OUTPUT>::type>
|
||||
void convolution_backprop_impl(const INPUT* in,
|
||||
const FILTER* filter,
|
||||
OUTPUT* out,
|
||||
namespace
|
||||
{
|
||||
constexpr size_t filter_input_ch_axis = 0;
|
||||
|
||||
template <typename T>
|
||||
void extend_with_zeros(const Strides& strides,
|
||||
const Shape& input_shape,
|
||||
const T* in,
|
||||
Shape& output_shape,
|
||||
std::vector<T>& input_zeros)
|
||||
{
|
||||
std::vector<int> input_3d(3, 1);
|
||||
std::vector<int> strides_3d(3, 1);
|
||||
std::vector<int> output_3d(3, 1);
|
||||
|
||||
for (size_t i = 0; i < strides.size(); ++i)
|
||||
{
|
||||
output_shape[i + 2] =
|
||||
input_shape[i + 2] + (strides[i] - 1) * (input_shape[i + 2] - 1);
|
||||
input_3d[input_3d.size() - strides.size() + i] = input_shape[i + 2];
|
||||
strides_3d[strides_3d.size() - strides.size() + i] = strides[i];
|
||||
output_3d[output_3d.size() - strides.size() + i] = output_shape[i + 2];
|
||||
}
|
||||
|
||||
const size_t input_size = shape_size(input_3d);
|
||||
if (input_size == 1)
|
||||
{
|
||||
for (size_t i = 0; i < shape_size(input_shape); ++i)
|
||||
{
|
||||
input_zeros.push_back(in[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t batch = 0; batch < input_shape[0]; ++batch)
|
||||
{
|
||||
const auto offset_batch = batch * input_size * input_shape[1];
|
||||
for (size_t channel = 0; channel < input_shape[1]; ++channel)
|
||||
{
|
||||
const auto offset_channel = offset_batch + channel * input_size;
|
||||
for (int i_z = 0; i_z < input_3d[0]; ++i_z)
|
||||
{
|
||||
const auto offset_i_z = i_z * input_3d[2] * input_3d[1];
|
||||
for (int i_y = 0; i_y < input_3d[1]; ++i_y)
|
||||
{
|
||||
const auto offset_i_y = i_y * input_3d[2];
|
||||
for (int i_x = 0; i_x < input_3d[2]; ++i_x)
|
||||
{
|
||||
input_zeros.push_back(
|
||||
in[offset_channel + i_x + offset_i_y + offset_i_z]);
|
||||
|
||||
if (i_x < input_3d[2] - 1)
|
||||
{
|
||||
for (int k = 0; k < strides_3d[2] - 1; k++)
|
||||
{
|
||||
input_zeros.push_back(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i_y < input_3d[1] - 1)
|
||||
{
|
||||
const auto new_size =
|
||||
output_3d[2] * (strides_3d[1] - 1);
|
||||
input_zeros.insert(input_zeros.begin() +
|
||||
input_zeros.size(),
|
||||
new_size,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
if (i_z < input_3d[0] - 1)
|
||||
{
|
||||
const auto new_size =
|
||||
output_3d[1] * output_3d[2] * (strides_3d[0] - 1);
|
||||
input_zeros.insert(
|
||||
input_zeros.begin() + input_zeros.size(), new_size, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void infer_forward_convbackprop_output_shape(const Shape& in_spatial_shape,
|
||||
const Shape& f_spatial_shape,
|
||||
const Shape& out_spatial_shape,
|
||||
Shape& infer_spatial_shape,
|
||||
const Strides& strides,
|
||||
const Strides& dilations,
|
||||
const CoordinateDiff& output_padding)
|
||||
{
|
||||
for (size_t idx = 0; idx < in_spatial_shape.size(); idx++)
|
||||
{
|
||||
int total_padding = strides[idx] * (in_spatial_shape[idx] - 1) +
|
||||
dilations[idx] * (f_spatial_shape[idx] - 1) + 1 -
|
||||
out_spatial_shape[idx] + output_padding[idx];
|
||||
size_t padded_dim = std::max<size_t>(total_padding, 0);
|
||||
size_t filter_dilated_dim = dilations[idx] * (f_spatial_shape[idx] - 1) + 1;
|
||||
size_t out_spatial_dim = (in_spatial_shape[idx] - 1) * strides[idx] +
|
||||
filter_dilated_dim - padded_dim +
|
||||
output_padding[idx];
|
||||
infer_spatial_shape.push_back(out_spatial_dim);
|
||||
}
|
||||
}
|
||||
|
||||
void validate_convolution_backprop_parameters(const Shape& in_shape,
|
||||
const Shape& f_shape,
|
||||
const Shape& out_shape,
|
||||
const Strides& strides,
|
||||
const Strides& dilations,
|
||||
const CoordinateDiff& pads_begin,
|
||||
const CoordinateDiff& pads_end,
|
||||
const CoordinateDiff& output_padding)
|
||||
{
|
||||
// this implementation supports 1D, 2D and 3D convolutions
|
||||
NGRAPH_CHECK(in_shape.size() >= 3 && in_shape.size() <= 5,
|
||||
"Unsupported input rank: ",
|
||||
in_shape);
|
||||
|
||||
NGRAPH_CHECK(in_shape.size() == f_shape.size(),
|
||||
"Incompatible input ranks: ",
|
||||
in_shape.size(),
|
||||
" and ",
|
||||
f_shape.size());
|
||||
|
||||
NGRAPH_CHECK(in_shape[in_channel_axis] == f_shape[filter_input_ch_axis],
|
||||
"Incompatible input channels in data batch and filters shapes: ",
|
||||
in_shape[in_channel_axis],
|
||||
" and ",
|
||||
f_shape[filter_input_ch_axis]);
|
||||
|
||||
NGRAPH_CHECK(in_shape.size() == out_shape.size(),
|
||||
"Incompatible input and output ranks: ",
|
||||
in_shape.size(),
|
||||
" and ",
|
||||
out_shape.size());
|
||||
|
||||
const auto spatial_dims = in_shape.size() - 2;
|
||||
NGRAPH_CHECK(strides.size() == spatial_dims,
|
||||
"Strides not definied for all and only spatial dimensions.");
|
||||
|
||||
NGRAPH_CHECK(dilations.size() == spatial_dims,
|
||||
"Dilations not defined for all and only spatial dimensions.");
|
||||
|
||||
NGRAPH_CHECK((pads_begin.size() == pads_end.size()) &&
|
||||
(pads_begin.size() == spatial_dims),
|
||||
"Pads not defined for all and only spatial dimensions.");
|
||||
|
||||
NGRAPH_CHECK(!output_padding.empty() && output_padding.size() == spatial_dims,
|
||||
"Output padding not defined for all and only spatial dimensions.");
|
||||
|
||||
Shape out_spatial_shape{std::next(out_shape.begin(), 2), std::end(out_shape)};
|
||||
Shape infered_out_spatial_shape{};
|
||||
infer_forward_convbackprop_output_shape(
|
||||
Shape{std::next(in_shape.begin(), 2), std::end(in_shape)},
|
||||
Shape{std::next(f_shape.begin(), 2), std::end(f_shape)},
|
||||
Shape{std::next(out_shape.begin(), 2), std::end(out_shape)},
|
||||
infered_out_spatial_shape,
|
||||
strides,
|
||||
dilations,
|
||||
output_padding);
|
||||
NGRAPH_CHECK(out_spatial_shape == infered_out_spatial_shape,
|
||||
"Incorrect output shape provided");
|
||||
}
|
||||
} // namespace
|
||||
|
||||
template <typename T>
|
||||
void convolution_backprop_impl(const T* in,
|
||||
const T* f,
|
||||
T* out,
|
||||
const Shape& in_shape,
|
||||
const Shape& f_shape,
|
||||
const Shape& out_shape,
|
||||
const Strides& strides,
|
||||
const Strides& dilation,
|
||||
const CoordinateDiff& pads_begin,
|
||||
const CoordinateDiff& pads_end,
|
||||
const CoordinateDiff& output_padding)
|
||||
|
||||
{
|
||||
// here we are converting all param types to int's to avoid arithmetic issues
|
||||
// (e.g signed + unsigned) in indexes calculation later
|
||||
ConvolutionParams params{strides, dilation, pads_begin, pads_end, output_padding};
|
||||
|
||||
// here we are extending spatial dimensions to 3D, because we are going to use 3D
|
||||
// convolution implementation to convolve also in 1D & 2D case
|
||||
Shape input_shape{in_shape};
|
||||
Shape filters_shape{f_shape};
|
||||
if (in_shape.size() < 5)
|
||||
{
|
||||
extend_to_3D(params, input_shape, filters_shape);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < input_shape.size() - 2; ++i)
|
||||
{
|
||||
if (input_shape[i + 2] > 1 || filters_shape[i + 2] > 1)
|
||||
{
|
||||
params.pads_begin[i] = filters_shape[i + 2] - params.pads_begin[i] - 1;
|
||||
params.pads_end[i] = filters_shape[i + 2] - params.pads_end[i] - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
params.pads_begin[i] = 0;
|
||||
params.pads_end[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// convert output shape to 3D, contains only dimensions
|
||||
Shape out_shape_3d{out_shape.begin() + 2, out_shape.end()};
|
||||
|
||||
int out_shape_rank = out_shape.size() - 2;
|
||||
if (out_shape_rank < 3)
|
||||
{
|
||||
int missing_dims = 3 - out_shape_rank;
|
||||
out_shape_3d.insert(
|
||||
std::prev(out_shape_3d.end(), out_shape_rank), missing_dims, 1);
|
||||
}
|
||||
|
||||
// modify params.pads_end when output_shape was provided in ctor in order to
|
||||
// calculate expected number of output elements
|
||||
for (size_t i = 0; i < out_shape_3d.size(); i++)
|
||||
{
|
||||
if (out_shape_3d[i] > 1)
|
||||
{
|
||||
// expected_dim = (in - 1)* strides + filter - 2*padding + out_padding
|
||||
// strides is already applied (through 0's extension in input)
|
||||
// padding = pads_begin + pads_end, formula below is using
|
||||
// params.pad_begin/params.pads_end:
|
||||
const size_t expected_dim =
|
||||
out_shape_3d[i] - ((input_shape[i + 2] - 1) - filters_shape[i + 2] +
|
||||
params.pads_begin[i] + params.pads_end[i] + 2 +
|
||||
params.output_padding[i]);
|
||||
params.pads_end[i] += expected_dim;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t filters_count = filters_shape[filter_out_ch_axis];
|
||||
const Shape filter_shape(++filters_shape.begin(), filters_shape.end());
|
||||
const size_t filter_size = shape_size(filter_shape);
|
||||
|
||||
const size_t batches_count = input_shape[in_batch_axis];
|
||||
Shape batch_shape(++input_shape.begin(), input_shape.end());
|
||||
const size_t batch_size = shape_size(batch_shape);
|
||||
|
||||
auto batch = in;
|
||||
|
||||
for (size_t batch_idx = 0; batch_idx < batches_count; ++batch_idx)
|
||||
{
|
||||
auto filter = f;
|
||||
for (size_t f_idx = 0; f_idx < filters_count; ++f_idx)
|
||||
{
|
||||
convolve_3D_channels(params, batch, batch_shape, filter, filter_shape, out);
|
||||
filter += filter_size;
|
||||
}
|
||||
batch += batch_size;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void convolution_backprop_in(const T* delta_in,
|
||||
const T* filter,
|
||||
T* delta_out,
|
||||
const Shape& in_shape,
|
||||
const Shape& filter_shape,
|
||||
const Shape& out_shape,
|
||||
const Strides& stride,
|
||||
const Strides& filter_dilation,
|
||||
const CoordinateDiff& in_pad_below,
|
||||
const CoordinateDiff& in_pad_above,
|
||||
const Strides& in_dilation,
|
||||
size_t in_batch_axis,
|
||||
size_t in_channel_axis,
|
||||
size_t filter_out_channel_axis,
|
||||
size_t filter_in_channel_axis,
|
||||
size_t out_batch_axis,
|
||||
size_t out_channel_axis)
|
||||
{
|
||||
auto old_mode = std::fegetround();
|
||||
std::fesetround(FE_TONEAREST);
|
||||
// Comments throughout assume without loss of generality that:
|
||||
//
|
||||
// * batch axes for both in and out are 0
|
||||
// * in channel axes for both in and filter are 1
|
||||
// * out channel axes for filter is 0
|
||||
// * out channel axis for out is 1
|
||||
|
||||
// At the outermost level we will walk over every out coordinate O.
|
||||
CoordinateTransform out_transform(out_shape);
|
||||
|
||||
for (const Coordinate& out_coord : out_transform)
|
||||
{
|
||||
// Our out coordinate O will have the form:
|
||||
//
|
||||
// (N,chan_out,i_1,...,i_n)
|
||||
|
||||
size_t batch_index = out_coord[out_batch_axis];
|
||||
size_t out_channel = out_coord[out_channel_axis];
|
||||
|
||||
// For the in we need to iterate the coordinate:
|
||||
//
|
||||
// I:
|
||||
//
|
||||
// over the range (noninclusive on the right):
|
||||
//
|
||||
// (N,0,s_1*i_1,s_2*i_2,...,s_n*i_n) ->
|
||||
//
|
||||
// (N+1,
|
||||
// chans_in_count,
|
||||
// s_1*i_1+ l_1*filter_dims_1,
|
||||
/// ...,
|
||||
/// s_n*i_n +l_n*filter_dims_n)
|
||||
//
|
||||
// with strides:
|
||||
//
|
||||
// (1,l_1,...,l_n).
|
||||
//
|
||||
// Note that we are iterating within the *padded* and *dilated* in batch, so
|
||||
// further down we must check the current coordinate is in the pad or dilation
|
||||
// gap.
|
||||
|
||||
size_t n_spatial_dimensions = in_shape.size() - 2;
|
||||
size_t n_in_channels = in_shape[in_channel_axis];
|
||||
|
||||
Coordinate in_transform_start(2 + n_spatial_dimensions);
|
||||
Coordinate in_transform_end(2 + n_spatial_dimensions);
|
||||
Strides in_transform_movement_strides(2 + n_spatial_dimensions, 1);
|
||||
CoordinateDiff in_transform_pad_below(2 + n_spatial_dimensions, 0);
|
||||
CoordinateDiff in_transform_pad_above(2 + n_spatial_dimensions, 0);
|
||||
Strides in_transform_dilation_strides(2 + n_spatial_dimensions, 1);
|
||||
|
||||
in_transform_start[in_batch_axis] = batch_index;
|
||||
in_transform_end[in_batch_axis] = batch_index + 1;
|
||||
in_transform_start[in_channel_axis] = 0;
|
||||
in_transform_end[in_channel_axis] = 1;
|
||||
|
||||
for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
|
||||
{
|
||||
size_t filter_dilation_stride = filter_dilation[i - 2];
|
||||
size_t filter_movement_stride = stride[i - 2];
|
||||
std::ptrdiff_t below_pad = in_pad_below[i - 2];
|
||||
std::ptrdiff_t above_pad = in_pad_above[i - 2];
|
||||
size_t in_dilation_stride = in_dilation[i - 2];
|
||||
|
||||
in_transform_start[i] = filter_movement_stride * out_coord[i];
|
||||
in_transform_end[i] = in_transform_start[i] +
|
||||
(filter_shape[i] - 1) * filter_dilation_stride + 1;
|
||||
in_transform_movement_strides[i] = filter_dilation_stride;
|
||||
in_transform_pad_below[i] = below_pad;
|
||||
in_transform_pad_above[i] = above_pad;
|
||||
in_transform_dilation_strides[i] = in_dilation_stride;
|
||||
}
|
||||
|
||||
AxisVector in_transform_axis_order(2 + n_spatial_dimensions);
|
||||
for (size_t i = 0; i < in_transform_axis_order.size(); i++)
|
||||
{
|
||||
in_transform_axis_order[i] = i;
|
||||
}
|
||||
CoordinateTransform in_transform(in_shape,
|
||||
in_transform_start,
|
||||
in_transform_end,
|
||||
in_transform_movement_strides,
|
||||
in_transform_axis_order,
|
||||
in_transform_pad_below,
|
||||
in_transform_pad_above,
|
||||
in_transform_dilation_strides);
|
||||
|
||||
// Simultaneously with iterating I, for the filter we need to iterate the
|
||||
// coordinate:
|
||||
//
|
||||
// F
|
||||
//
|
||||
// over the range (noninclusive on the right):
|
||||
//
|
||||
// (chan_out,0,0,...,0) ->
|
||||
// (chan_out+1,
|
||||
// chans_in_count,
|
||||
// filter_dims_1,
|
||||
// ...,
|
||||
// filter_dims_n)
|
||||
//
|
||||
// with unit stride.
|
||||
|
||||
Shape filter_transform_start(2 + n_spatial_dimensions);
|
||||
Shape filter_transform_end(2 + n_spatial_dimensions);
|
||||
|
||||
filter_transform_start[filter_out_channel_axis] = out_channel;
|
||||
filter_transform_end[filter_out_channel_axis] = out_channel + 1;
|
||||
filter_transform_start[filter_in_channel_axis] = 0;
|
||||
filter_transform_end[filter_in_channel_axis] = 1;
|
||||
|
||||
for (size_t i = 2; i < n_spatial_dimensions + 2; i++)
|
||||
{
|
||||
filter_transform_start[i] = 0;
|
||||
filter_transform_end[i] = filter_shape[i];
|
||||
}
|
||||
|
||||
CoordinateTransform filter_transform(
|
||||
filter_shape, filter_transform_start, filter_transform_end);
|
||||
|
||||
// As we go, we sum up:
|
||||
//
|
||||
// out[O] += in[I] * filter[F].
|
||||
|
||||
ACCUMULATION result = 0;
|
||||
|
||||
CoordinateTransform::Iterator in_it = in_transform.begin();
|
||||
CoordinateTransform::Iterator filter_it = filter_transform.begin();
|
||||
CoordinateTransform::Iterator in_it_end = in_transform.end();
|
||||
CoordinateTransform::Iterator filter_it_end = filter_transform.end();
|
||||
|
||||
size_t in_channel_stride = row_major_strides(in_shape).at(in_channel_axis);
|
||||
size_t filter_in_channel_stride =
|
||||
row_major_strides(filter_shape).at(filter_in_channel_axis);
|
||||
|
||||
while (in_it != in_it_end && filter_it != filter_it_end)
|
||||
{
|
||||
const Coordinate& in_coord = *in_it;
|
||||
if (in_transform.has_source_coordinate(in_coord))
|
||||
{
|
||||
size_t in_idx = in_transform.index(in_coord);
|
||||
const Coordinate& filter_coord = *filter_it;
|
||||
size_t filter_idx = filter_transform.index(filter_coord);
|
||||
for (size_t in_channel = 0; in_channel < n_in_channels; ++in_channel)
|
||||
{
|
||||
ACCUMULATION in_v = static_cast<ACCUMULATION>(in[in_idx]);
|
||||
ACCUMULATION f_v = static_cast<ACCUMULATION>(filter[filter_idx]);
|
||||
|
||||
result += in_v * f_v;
|
||||
in_idx += in_channel_stride;
|
||||
filter_idx += filter_in_channel_stride;
|
||||
}
|
||||
}
|
||||
++in_it;
|
||||
++filter_it;
|
||||
}
|
||||
|
||||
out[out_transform.index(out_coord)] = result;
|
||||
}
|
||||
std::fesetround(old_mode);
|
||||
}
|
||||
|
||||
template <typename OUTPUT,
|
||||
typename FILTER,
|
||||
typename INPUT,
|
||||
typename ACCUMULATION = typename widen<INPUT>::type>
|
||||
void convolution_backprop_in(const OUTPUT* delta_out,
|
||||
const FILTER* filter,
|
||||
INPUT* delta_in,
|
||||
const Shape& out_shape,
|
||||
const Shape& filter_shape,
|
||||
const Shape& in_shape,
|
||||
const Strides& in_dilation,
|
||||
const Strides& filter_dilation,
|
||||
const CoordinateDiff& forward_in_pad_bellow,
|
||||
const CoordinateDiff& forward_in_pad_above,
|
||||
const Strides& stride)
|
||||
const Strides& stride,
|
||||
const CoordinateDiff& output_padding)
|
||||
{
|
||||
std::vector<T> extended_input;
|
||||
std::vector<T> extended_filter;
|
||||
AxisSet reverse_axes;
|
||||
|
||||
Shape conv_input_shape = in_shape;
|
||||
Shape conv_filter_shape = filter_shape;
|
||||
Strides conv_stride = stride;
|
||||
Strides conv_filter_dilation = filter_dilation;
|
||||
auto conv_input_data = delta_in;
|
||||
|
||||
validate_convolution_backprop_parameters(in_shape,
|
||||
filter_shape,
|
||||
out_shape,
|
||||
stride,
|
||||
filter_dilation,
|
||||
forward_in_pad_bellow,
|
||||
forward_in_pad_above,
|
||||
output_padding);
|
||||
|
||||
// Note that we only reverse the spatial dimensions here (loop
|
||||
// starts at 2)
|
||||
std::vector<INPUT> reversed(shape_size(filter_shape));
|
||||
AxisSet reverse_axes;
|
||||
size_t reverse_axes_start = 2;
|
||||
for (size_t i = reverse_axes_start; i < filter_shape.size(); ++i)
|
||||
std::vector<T> reversed(shape_size(filter_shape));
|
||||
for (size_t i = 2; i < filter_shape.size(); ++i)
|
||||
{
|
||||
reverse_axes.insert(i);
|
||||
}
|
||||
@ -242,55 +323,109 @@ namespace ngraph
|
||||
filter_shape,
|
||||
filter_shape,
|
||||
reverse_axes,
|
||||
sizeof(FILTER));
|
||||
size_t filter_out_channel_axis = 1;
|
||||
size_t filter_in_channel_axis = 0;
|
||||
sizeof(T));
|
||||
|
||||
// Compute backward pad out pad bellow
|
||||
size_t spatial_dim_count = in_shape.size() - 2;
|
||||
auto conv_filter_data = &reversed[0];
|
||||
|
||||
CoordinateDiff backward_delta_out_pad_below;
|
||||
backward_delta_out_pad_below.resize(spatial_dim_count);
|
||||
|
||||
for (size_t i = 0; i < spatial_dim_count; i++)
|
||||
// if channel number for output is > 1 then reverse layout of filter coefficients as
|
||||
// it is required by convolve_3D_channels() function.
|
||||
// Current layout:
|
||||
// batch0_ch0|batch0_ch1|...|batch0_chN|...|batch1_ch0|batch1_ch1|...|batch1_chN|...
|
||||
// Expected layout:
|
||||
// batch0_ch0|batch1_ch0|...|batchN_ch0|...|batch0_ch1|batch1_ch1|...|batch1_chN|...
|
||||
if (filter_shape[1] > 1)
|
||||
{
|
||||
backward_delta_out_pad_below[i] =
|
||||
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i] -
|
||||
forward_in_pad_bellow[i];
|
||||
std::vector<T> temp_reversed(reversed);
|
||||
const Shape filter_dim_shape(filter_shape.begin() + 2, filter_shape.end());
|
||||
const size_t filter_size = shape_size(filter_dim_shape);
|
||||
|
||||
for (size_t i = 0; i < filter_shape[1]; i++)
|
||||
{
|
||||
for (size_t j = 0; j < filter_shape[0]; j++)
|
||||
{
|
||||
const auto delta = temp_reversed.begin() +
|
||||
j * filter_shape[1] * filter_size + i * filter_size;
|
||||
const auto out = reversed.begin() + i * filter_shape[0] * filter_size +
|
||||
j * filter_size;
|
||||
std::copy(delta, delta + filter_size, out);
|
||||
}
|
||||
}
|
||||
// Compute backward pad out pad above
|
||||
CoordinateDiff backward_delta_out_pad_above;
|
||||
backward_delta_out_pad_above.resize(spatial_dim_count);
|
||||
|
||||
for (size_t i = 0; i < spatial_dim_count; i++)
|
||||
{
|
||||
backward_delta_out_pad_above[i] =
|
||||
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i] +
|
||||
((forward_in_pad_bellow[i] + ((in_shape[i + 2]) - 1) * in_dilation[i] +
|
||||
forward_in_pad_above[i] -
|
||||
(static_cast<ptrdiff_t>(filter_shape[i + 2]) - 1) * filter_dilation[i]) %
|
||||
stride[i]) -
|
||||
forward_in_pad_above[i];
|
||||
}
|
||||
|
||||
convolution_backprop_impl<OUTPUT, FILTER, INPUT, ACCUMULATION>(
|
||||
delta_out,
|
||||
&reversed[0],
|
||||
delta_in,
|
||||
out_shape,
|
||||
// swap filter batch and channels
|
||||
std::iter_swap(conv_filter_shape.begin(), conv_filter_shape.begin() + 1);
|
||||
|
||||
// extend stride and filter inputs with zero padding for stride and filter_dilation
|
||||
// > 1, after that set stride and filter params to 1.
|
||||
const size_t stride_dim =
|
||||
std::accumulate(stride.begin(), stride.end(), 1, std::multiplies<size_t>());
|
||||
if (stride_dim >= 2)
|
||||
{
|
||||
extend_with_zeros(stride, in_shape, delta_in, conv_input_shape, extended_input);
|
||||
std::fill(conv_stride.begin(), conv_stride.end(), 1);
|
||||
conv_input_data = &extended_input[0];
|
||||
}
|
||||
|
||||
const size_t dilation_dim = std::accumulate(
|
||||
filter_dilation.begin(), filter_dilation.end(), 1, std::multiplies<size_t>());
|
||||
if (dilation_dim >= 2)
|
||||
{
|
||||
extend_with_zeros<T>(filter_dilation,
|
||||
filter_shape,
|
||||
reinterpret_cast<const T*>(&reversed[0]),
|
||||
conv_filter_shape,
|
||||
extended_filter);
|
||||
std::fill(conv_filter_dilation.begin(), conv_filter_dilation.end(), 1);
|
||||
conv_filter_data = &extended_filter[0];
|
||||
}
|
||||
|
||||
convolution_backprop_impl(conv_input_data,
|
||||
conv_filter_data,
|
||||
delta_out,
|
||||
conv_input_shape,
|
||||
conv_filter_shape,
|
||||
out_shape,
|
||||
conv_stride,
|
||||
conv_filter_dilation,
|
||||
forward_in_pad_bellow,
|
||||
forward_in_pad_above,
|
||||
output_padding);
|
||||
}
|
||||
|
||||
// DEPRECATED, can't be removed currently due to arm-plugin dependency
|
||||
template <typename OUTPUT,
|
||||
typename FILTER,
|
||||
typename INPUT,
|
||||
typename ACCUMULATION = typename widen<INPUT>::type>
|
||||
NGRAPH_DEPRECATED(
|
||||
"convolution_backprop_in function with 4 template types is deprecated, use "
|
||||
"function with 1 template and output_padding parameter.")
|
||||
void convolution_backprop_in(const INPUT* delta_in,
|
||||
const FILTER* filter,
|
||||
OUTPUT* delta_out,
|
||||
const Shape& in_shape,
|
||||
const Shape& filter_shape,
|
||||
const Shape& out_shape,
|
||||
const Strides& in_dilation,
|
||||
const Strides& filter_dilation,
|
||||
const CoordinateDiff& forward_in_pad_bellow,
|
||||
const CoordinateDiff& forward_in_pad_above,
|
||||
const Strides& stride)
|
||||
{
|
||||
const ngraph::CoordinateDiff output_padding(in_shape.size() - 2, 0);
|
||||
|
||||
convolution_backprop_in(delta_in,
|
||||
filter,
|
||||
delta_out,
|
||||
in_shape,
|
||||
filter_shape,
|
||||
out_shape,
|
||||
in_dilation,
|
||||
filter_dilation,
|
||||
backward_delta_out_pad_below,
|
||||
backward_delta_out_pad_above,
|
||||
forward_in_pad_bellow,
|
||||
forward_in_pad_above,
|
||||
stride,
|
||||
0,
|
||||
1,
|
||||
filter_out_channel_axis,
|
||||
filter_in_channel_axis,
|
||||
0,
|
||||
1);
|
||||
output_padding);
|
||||
}
|
||||
} // namespace reference
|
||||
} // namespace runtime
|
||||
|
@ -178,13 +178,13 @@ namespace ngraph
|
||||
const size_t group_out_size = shape_size(group_out_shape);
|
||||
|
||||
Strides in_dilation(in_shape.size(), 1);
|
||||
const ngraph::CoordinateDiff output_padding(in_shape.size() - 2, 0);
|
||||
for (size_t batch_idx = 0; batch_idx < in_shape[in_batch_axis]; ++batch_idx)
|
||||
{
|
||||
group_filter = f;
|
||||
for (size_t group_idx = 0; group_idx < group_count; ++group_idx)
|
||||
{
|
||||
runtime::reference::convolution_backprop_in<INPUT, FILTER, OUTPUT, ACCU>(
|
||||
group_batch,
|
||||
runtime::reference::convolution_backprop_in(group_batch,
|
||||
group_filter,
|
||||
group_out,
|
||||
group_batch_shape,
|
||||
@ -194,7 +194,8 @@ namespace ngraph
|
||||
dilation,
|
||||
pads_begin,
|
||||
pads_end,
|
||||
strides);
|
||||
strides,
|
||||
output_padding);
|
||||
group_batch += group_batch_size;
|
||||
group_filter += group_filter_size;
|
||||
group_out += group_out_size;
|
||||
|
@ -35,7 +35,7 @@ namespace ngraph
|
||||
arg[transform.index(coord)] - temp_max[temp_transform.index(temp_coord)]);
|
||||
}
|
||||
|
||||
sum(out, temp_sum.data(), shape, axes, true);
|
||||
sum(out, temp_sum.data(), shape, axes);
|
||||
|
||||
for (const Coordinate& coord : transform)
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ namespace ngraph
|
||||
}
|
||||
|
||||
std::vector<T> sum_data(shape_size(reduce_shape));
|
||||
sum(sqr_data.data(), sum_data.data(), data_shape, axes, true);
|
||||
sum(sqr_data.data(), sum_data.data(), data_shape, axes);
|
||||
autobroadcast_binop(data,
|
||||
sum_data.data(),
|
||||
out,
|
||||
|
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
|
||||
#include "ngraph/coordinate_transform.hpp"
|
||||
#include "ngraph/shape_util.hpp"
|
||||
@ -16,29 +17,27 @@ namespace ngraph
|
||||
namespace reference
|
||||
{
|
||||
template <typename T>
|
||||
void product(const T* arg,
|
||||
T* out,
|
||||
const Shape& in_shape,
|
||||
const AxisSet& reduction_axes,
|
||||
bool keep_dims)
|
||||
void product(const T* arg, T* out, const Shape& in_shape, const AxisSet& reduction_axes)
|
||||
{
|
||||
auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
|
||||
CoordinateTransform output_transform(out_shape);
|
||||
constexpr bool dont_keep_dims_in_output = false;
|
||||
const auto out_shape = reduce(in_shape, reduction_axes, dont_keep_dims_in_output);
|
||||
std::fill(out, out + shape_size(out_shape), 1);
|
||||
|
||||
for (const Coordinate& output_coord : output_transform)
|
||||
{
|
||||
out[output_transform.index(output_coord)] = 1;
|
||||
}
|
||||
|
||||
CoordinateTransform input_transform(in_shape);
|
||||
const auto in_strides = row_major_strides(in_shape);
|
||||
const auto out_strides = row_major_strides(out_shape);
|
||||
|
||||
CoordinateTransformBasic input_transform(in_shape);
|
||||
for (const Coordinate& input_coord : input_transform)
|
||||
{
|
||||
Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
|
||||
const Coordinate output_coord =
|
||||
reduce(input_coord, reduction_axes, dont_keep_dims_in_output);
|
||||
|
||||
size_t output_index = output_transform.index(output_coord);
|
||||
const size_t in_idx = std::inner_product(
|
||||
input_coord.begin(), input_coord.end(), in_strides.begin(), 0);
|
||||
const size_t out_idx = std::inner_product(
|
||||
output_coord.begin(), output_coord.end(), out_strides.begin(), 0);
|
||||
|
||||
out[output_index] = out[output_index] * arg[input_transform.index(input_coord)];
|
||||
out[out_idx] = out[out_idx] * arg[in_idx];
|
||||
}
|
||||
}
|
||||
} // namespace reference
|
||||
|
@ -34,7 +34,7 @@ namespace ngraph
|
||||
arg[transform.index(coord)] - temp_ptr[temp_transform.index(temp_coord)]);
|
||||
}
|
||||
|
||||
sum(out, temp_ptr, shape, axes, true);
|
||||
sum(out, temp_ptr, shape, axes);
|
||||
|
||||
for (const Coordinate& coord : transform)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <numeric>
|
||||
|
||||
#include "ngraph/coordinate_transform.hpp"
|
||||
#include "ngraph/shape_util.hpp"
|
||||
@ -41,34 +42,34 @@ namespace ngraph
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void sum(const T* arg,
|
||||
T* out,
|
||||
const Shape& in_shape,
|
||||
const AxisSet& reduction_axes,
|
||||
bool keep_dims)
|
||||
void sum(const T* arg, T* out, const Shape& in_shape, const AxisSet& reduction_axes)
|
||||
{
|
||||
auto out_shape = reduce(in_shape, reduction_axes, keep_dims);
|
||||
CoordinateTransform output_transform(out_shape);
|
||||
std::vector<T> cs(shape_size(out_shape));
|
||||
constexpr bool dont_keep_dims_in_output = false;
|
||||
const auto out_shape = reduce(in_shape, reduction_axes, dont_keep_dims_in_output);
|
||||
|
||||
for (const Coordinate& output_coord : output_transform)
|
||||
{
|
||||
out[output_transform.index(output_coord)] = 0;
|
||||
cs[output_transform.index(output_coord)] = 0;
|
||||
}
|
||||
std::vector<T> cs(shape_size(out_shape), 0);
|
||||
std::fill(out, out + shape_size(out_shape), 0);
|
||||
|
||||
CoordinateTransform input_transform(in_shape);
|
||||
const auto in_strides = row_major_strides(in_shape);
|
||||
const auto out_strides = row_major_strides(out_shape);
|
||||
|
||||
CoordinateTransformBasic input_transform(in_shape);
|
||||
for (const Coordinate& input_coord : input_transform)
|
||||
{
|
||||
Coordinate output_coord = reduce(input_coord, reduction_axes, keep_dims);
|
||||
const Coordinate output_coord =
|
||||
reduce(input_coord, reduction_axes, dont_keep_dims_in_output);
|
||||
|
||||
T x = arg[input_transform.index(input_coord)];
|
||||
T& z = out[output_transform.index(output_coord)];
|
||||
const size_t in_idx = std::inner_product(
|
||||
input_coord.begin(), input_coord.end(), in_strides.begin(), 0);
|
||||
const size_t out_idx = std::inner_product(
|
||||
output_coord.begin(), output_coord.end(), out_strides.begin(), 0);
|
||||
|
||||
T x = arg[in_idx];
|
||||
T& z = out[out_idx];
|
||||
|
||||
if (is_finite(x) && is_finite(z))
|
||||
{
|
||||
T& c = cs[output_transform.index(output_coord)];
|
||||
T& c = cs[out_idx];
|
||||
T t = z + (x - c);
|
||||
c = (t - z) - (x - c);
|
||||
z = t;
|
||||
|
@ -436,8 +436,7 @@ namespace ngraph
|
||||
ngraph::runtime::reference::sum<T>(input_ptr->get_data_ptr<T>(),
|
||||
output_ptr->get_data_ptr<T>(),
|
||||
input_shape,
|
||||
reduced_axes,
|
||||
false);
|
||||
reduced_axes);
|
||||
|
||||
// update a vector of inputs and input subscripts
|
||||
inputs[input_ind] = output_ptr;
|
||||
@ -743,8 +742,7 @@ namespace ngraph
|
||||
ngraph::runtime::reference::sum<T>(mul_output->get_data_ptr<T>(),
|
||||
result->get_data_ptr<T>(),
|
||||
mul_output->get_shape(),
|
||||
reduced_axes,
|
||||
false);
|
||||
reduced_axes);
|
||||
inputs[input_ind] = result;
|
||||
input_subscripts[input_ind] = resultant_subscript;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <ngraph/validation_util.hpp>
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/graph_util.hpp"
|
||||
#include "ngraph/op/util/evaluate_helpers.hpp"
|
||||
#include "ngraph/runtime/host_tensor.hpp"
|
||||
#include "ngraph/runtime/reference/product.hpp"
|
||||
#include "ngraph/shape_util.hpp"
|
||||
@ -45,7 +46,7 @@ namespace reduce_prod
|
||||
{
|
||||
out->set_shape(reduce(arg->get_shape(), axes, keep_dims));
|
||||
runtime::reference::product(
|
||||
arg->get_data_ptr<ET>(), out->get_data_ptr<ET>(), arg->get_shape(), axes, keep_dims);
|
||||
arg->get_data_ptr<ET>(), out->get_data_ptr<ET>(), arg->get_shape(), axes);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,8 +76,11 @@ bool op::v1::ReduceProd::evaluate(const HostTensorVector& outputs,
|
||||
NGRAPH_OP_SCOPE(v1_ReduceProd_evaluate);
|
||||
NGRAPH_CHECK(validate_host_tensor_vector(inputs, 2));
|
||||
NGRAPH_CHECK(validate_host_tensor_vector(outputs, 1));
|
||||
return reduce_prod::evaluate_product(
|
||||
inputs[0], outputs[0], get_reduction_axes(), get_keep_dims());
|
||||
|
||||
const auto reduction_axes = get_normalized_axes_from_tensor(
|
||||
inputs[1], inputs[0]->get_partial_shape().rank(), get_friendly_name());
|
||||
|
||||
return reduce_prod::evaluate_product(inputs[0], outputs[0], reduction_axes, get_keep_dims());
|
||||
}
|
||||
|
||||
bool op::v1::ReduceProd::has_evaluate() const
|
||||
|
@ -3,14 +3,15 @@
|
||||
//
|
||||
|
||||
#include "ngraph/op/reduce_sum.hpp"
|
||||
#include <ngraph/validation_util.hpp>
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/graph_util.hpp"
|
||||
#include "ngraph/op/broadcast.hpp"
|
||||
#include "ngraph/op/util/evaluate_helpers.hpp"
|
||||
#include "ngraph/op/util/op_types.hpp"
|
||||
#include "ngraph/runtime/host_tensor.hpp"
|
||||
#include "ngraph/runtime/reference/sum.hpp"
|
||||
#include "ngraph/shape_util.hpp"
|
||||
#include "util/evaluate_helpers.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
@ -47,7 +48,7 @@ namespace reduce_sum
|
||||
{
|
||||
out->set_shape(reduce(arg->get_shape(), axes, keep_dims));
|
||||
runtime::reference::sum(
|
||||
arg->get_data_ptr<ET>(), out->get_data_ptr<ET>(), arg->get_shape(), axes, keep_dims);
|
||||
arg->get_data_ptr<ET>(), out->get_data_ptr<ET>(), arg->get_shape(), axes);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -75,13 +76,11 @@ bool op::v1::ReduceSum::evaluate(const HostTensorVector& outputs,
|
||||
const HostTensorVector& inputs) const
|
||||
{
|
||||
NGRAPH_OP_SCOPE(v1_ReduceSum_evaluate);
|
||||
|
||||
NGRAPH_CHECK(inputs.size() == 2,
|
||||
"The ReduceSum operation expects 2 input tensors. Got: ",
|
||||
inputs.size());
|
||||
NGRAPH_CHECK(validate_host_tensor_vector(inputs, 2));
|
||||
NGRAPH_CHECK(validate_host_tensor_vector(outputs, 1));
|
||||
|
||||
const auto reduction_axes = get_normalized_axes_from_tensor(
|
||||
inputs[1], get_input_partial_shape(0).rank(), get_friendly_name());
|
||||
inputs[1], inputs[0]->get_partial_shape().rank(), get_friendly_name());
|
||||
|
||||
return reduce_sum::evaluate_sum(inputs[0], outputs[0], reduction_axes, get_keep_dims());
|
||||
}
|
||||
|
@ -5,65 +5,53 @@
|
||||
#include "ngraph/op/selu.hpp"
|
||||
#include "itt.hpp"
|
||||
|
||||
#include "ngraph/op/add.hpp"
|
||||
#include "ngraph/op/constant.hpp"
|
||||
#include "ngraph/op/exp.hpp"
|
||||
#include "ngraph/op/maximum.hpp"
|
||||
#include "ngraph/op/minimum.hpp"
|
||||
#include "ngraph/op/multiply.hpp"
|
||||
#include "ngraph/op/subtract.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
NGRAPH_SUPPRESS_DEPRECATED_START
|
||||
|
||||
constexpr NodeTypeInfo op::v0::Selu::type_info;
|
||||
|
||||
op::v0::Selu::Selu()
|
||||
: FusedOp()
|
||||
{
|
||||
}
|
||||
NGRAPH_RTTI_DEFINITION(op::v0::Selu, "Selu", 0);
|
||||
|
||||
op::v0::Selu::Selu(const Output<Node>& data, const Output<Node>& alpha, const Output<Node>& lambda)
|
||||
: FusedOp({data, alpha, lambda})
|
||||
: Op({data, alpha, lambda})
|
||||
{
|
||||
constructor_validate_and_infer_types();
|
||||
}
|
||||
|
||||
void ngraph::op::v0::Selu::pre_validate_and_infer_types()
|
||||
void op::v0::Selu::validate_and_infer_types()
|
||||
{
|
||||
set_output_type(0, get_input_element_type(0), get_input_partial_shape(0));
|
||||
NGRAPH_OP_SCOPE(v0_Selu_validate_and_infer_types);
|
||||
auto data_et = get_input_element_type(0);
|
||||
auto alpha_et = get_input_element_type(1);
|
||||
auto lambda_et = get_input_element_type(2);
|
||||
auto result_et = element::dynamic;
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
element::Type::merge(result_et, result_et, data_et) &&
|
||||
element::Type::merge(result_et, result_et, alpha_et) &&
|
||||
element::Type::merge(result_et, result_et, lambda_et),
|
||||
"Input element types do not match : ",
|
||||
data_et,
|
||||
" and ",
|
||||
alpha_et,
|
||||
" and ",
|
||||
lambda_et);
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
result_et.is_dynamic() || result_et.is_real(),
|
||||
"Input element types must be floating-point. Got: ",
|
||||
result_et);
|
||||
|
||||
set_output_type(0, result_et, get_input_partial_shape(0));
|
||||
}
|
||||
|
||||
bool ngraph::op::v0::Selu::visit_attributes(AttributeVisitor& visitor)
|
||||
bool op::v0::Selu::visit_attributes(AttributeVisitor& visitor)
|
||||
{
|
||||
NGRAPH_OP_SCOPE(v0_Selu_visit_attributes);
|
||||
return true;
|
||||
}
|
||||
|
||||
OutputVector op::v0::Selu::decompose_op() const
|
||||
{
|
||||
const auto data = input_value(0);
|
||||
const auto alpha = input_value(1);
|
||||
const auto lambda = input_value(2);
|
||||
const auto zero_node = op::Constant::create(data.get_element_type(), Shape{1}, {0});
|
||||
|
||||
// lambda * ((max(data, 0) + (alpha * exp(min(data, 0)) - alpha))
|
||||
return {std::make_shared<op::v1::Multiply>(
|
||||
lambda,
|
||||
std::make_shared<op::v1::Add>(
|
||||
std::make_shared<op::v1::Maximum>(data, zero_node),
|
||||
std::make_shared<op::v1::Subtract>(
|
||||
std::make_shared<op::v1::Multiply>(
|
||||
alpha,
|
||||
std::make_shared<op::Exp>(std::make_shared<op::v1::Minimum>(data, zero_node))),
|
||||
alpha)))};
|
||||
}
|
||||
|
||||
shared_ptr<Node> op::v0::Selu::clone_with_new_inputs(const OutputVector& new_args) const
|
||||
{
|
||||
NGRAPH_OP_SCOPE(v0_Selu_clone_with_new_inputs);
|
||||
check_new_args_count(this, new_args);
|
||||
return make_shared<v0::Selu>(new_args.at(0), new_args.at(1), new_args.at(2));
|
||||
return make_shared<op::v0::Selu>(new_args.at(0), new_args.at(1), new_args.at(2));
|
||||
}
|
||||
|
@ -21,7 +21,7 @@
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
constexpr NodeTypeInfo op::v1::SpaceToBatch::type_info;
|
||||
NGRAPH_RTTI_DEFINITION(op::v1::SpaceToBatch, "SpaceToBatch", 1);
|
||||
|
||||
ngraph::op::v1::SpaceToBatch::SpaceToBatch(const ngraph::Output<ngraph::Node>& data,
|
||||
const ngraph::Output<ngraph::Node>& block_shape,
|
||||
@ -49,13 +49,13 @@ void op::v1::SpaceToBatch::validate_and_infer_types()
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
pads_begin_type.is_integral_number(),
|
||||
"crops_begin must be an integral number but got (",
|
||||
"pads_begin must be an integral number but got (",
|
||||
pads_begin_type,
|
||||
").");
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
pads_end_type.is_integral_number(),
|
||||
"crops_end must be an integral number but got (",
|
||||
"pads_end must be an integral number but got (",
|
||||
pads_end_type,
|
||||
").");
|
||||
|
||||
|
@ -16,7 +16,7 @@ op::util::ArithmeticReduction::ArithmeticReduction() {}
|
||||
|
||||
op::util::ArithmeticReduction::ArithmeticReduction(const Output<Node>& arg,
|
||||
const Output<Node>& reduction_axes)
|
||||
: Op({arg, reduction_axes})
|
||||
: ReductionBase(arg, reduction_axes)
|
||||
{
|
||||
}
|
||||
|
||||
@ -49,51 +49,15 @@ void op::util::ArithmeticReduction::set_reduction_axes(const AxisSet& reduction_
|
||||
void op::util::ArithmeticReduction::validate_and_infer_types()
|
||||
{
|
||||
NGRAPH_OP_SCOPE(util_ArithmeticReduction_validate_and_infer_types);
|
||||
auto input_shape = get_input_partial_shape(0);
|
||||
const auto input_rank = input_shape.rank();
|
||||
|
||||
PartialShape result_shape{PartialShape::dynamic()};
|
||||
|
||||
auto axes = get_constant_from_source(input_value(1));
|
||||
if (input_rank.is_static() && axes)
|
||||
{
|
||||
AxisSet reduction_axes;
|
||||
const auto reduction_axes_val = axes->cast_vector<int64_t>();
|
||||
for (auto axis : reduction_axes_val)
|
||||
{
|
||||
try
|
||||
{
|
||||
axis = normalize_axis(this, axis, input_rank);
|
||||
}
|
||||
catch (const ngraph_error&)
|
||||
{
|
||||
const PartialShape& axes_shape = get_input_partial_shape(1);
|
||||
const Rank axes_rank = axes_shape.rank();
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
false,
|
||||
"Reduction axis (",
|
||||
axis,
|
||||
") is out of bounds ",
|
||||
"(argument shape: ",
|
||||
input_shape,
|
||||
", reduction axes: ",
|
||||
reduction_axes,
|
||||
")");
|
||||
}
|
||||
reduction_axes.insert(axis);
|
||||
}
|
||||
|
||||
std::vector<Dimension> dims;
|
||||
for (int64_t i = 0; i < input_rank.get_length(); i++)
|
||||
{
|
||||
if (reduction_axes.count(i) == 0)
|
||||
{
|
||||
dims.push_back(input_shape[i]);
|
||||
}
|
||||
}
|
||||
|
||||
result_shape = PartialShape(dims);
|
||||
}
|
||||
axes_rank.compatible(0) || axes_rank.compatible(1),
|
||||
"Axes input must be a scalar or 1D input. Got: ",
|
||||
axes_shape);
|
||||
|
||||
PartialShape result_shape = infer_reduction_output_shape(false);
|
||||
set_input_is_relevant_to_shape(1);
|
||||
|
||||
set_output_type(0, get_input_element_type(0), result_shape);
|
||||
}
|
||||
|
@ -32,61 +32,28 @@ bool ngraph::op::util::ArithmeticReductionKeepDims::visit_attributes(AttributeVi
|
||||
void op::util::ArithmeticReductionKeepDims::validate_and_infer_types()
|
||||
{
|
||||
NGRAPH_OP_SCOPE(v0_util_ArithmeticReductionKeepDims_validate_and_infer_types);
|
||||
if (m_keep_dims)
|
||||
{
|
||||
auto input_shape = get_input_partial_shape(0);
|
||||
auto input_rank = input_shape.rank();
|
||||
PartialShape result_shape{PartialShape::dynamic()};
|
||||
|
||||
if (input_rank.is_static())
|
||||
result_shape = PartialShape::dynamic(input_rank);
|
||||
const element::Type& data_et = get_input_element_type(0);
|
||||
const PartialShape& axes_shape = get_input_partial_shape(1);
|
||||
const element::Type& axes_et = get_input_element_type(1);
|
||||
|
||||
const auto& axes = get_constant_from_source(input_value(1));
|
||||
if (input_rank.is_static() && axes)
|
||||
{
|
||||
AxisSet reduction_axes;
|
||||
auto reduction_axes_val = axes->cast_vector<int64_t>();
|
||||
for (auto axis : reduction_axes_val)
|
||||
{
|
||||
try
|
||||
{
|
||||
axis = normalize_axis(this, axis, input_rank);
|
||||
}
|
||||
catch (const ngraph_error&)
|
||||
{
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
false,
|
||||
"Reduction axis (",
|
||||
axis,
|
||||
") is out of bounds ",
|
||||
"(argument shape: ",
|
||||
input_shape,
|
||||
", reduction axes: ",
|
||||
reduction_axes,
|
||||
")");
|
||||
}
|
||||
reduction_axes.insert(axis);
|
||||
}
|
||||
data_et.is_real() || data_et.is_integral_number(),
|
||||
"Element type of data input must be numeric. Got: ",
|
||||
data_et);
|
||||
|
||||
std::vector<Dimension> dims;
|
||||
for (int64_t i = 0; i < input_rank.get_length(); i++)
|
||||
{
|
||||
if (reduction_axes.count(i) == 0)
|
||||
{
|
||||
dims.push_back(input_shape[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dims.emplace_back(Dimension{1});
|
||||
}
|
||||
}
|
||||
result_shape = PartialShape(dims);
|
||||
}
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
axes_et.is_integral_number(),
|
||||
"Element type of axes input must be integer. Got: ",
|
||||
axes_et);
|
||||
|
||||
const Rank axes_rank = axes_shape.rank();
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
axes_rank.compatible(0) || axes_rank.compatible(1),
|
||||
"Axes input must be a scalar or 1D input. Got: ",
|
||||
axes_shape);
|
||||
|
||||
PartialShape result_shape = infer_reduction_output_shape(m_keep_dims);
|
||||
set_input_is_relevant_to_shape(1);
|
||||
set_output_type(0, get_input_element_type(0), result_shape);
|
||||
}
|
||||
else
|
||||
{
|
||||
ArithmeticReduction::validate_and_infer_types();
|
||||
}
|
||||
set_output_type(0, data_et, result_shape);
|
||||
}
|
||||
|
17
ngraph/core/src/op/util/evaluate_helpers.cpp
Normal file
17
ngraph/core/src/op/util/evaluate_helpers.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph/op/util/evaluate_helpers.hpp"
|
||||
|
||||
namespace ngraph
|
||||
{
|
||||
AxisSet get_normalized_axes_from_tensor(const HostTensorPtr tensor,
|
||||
const ngraph::Rank& rank,
|
||||
const std::string& node_description)
|
||||
{
|
||||
const auto axes_vector = host_tensor_2_vector<int64_t>(tensor);
|
||||
const auto normalized_axes = ngraph::normalize_axes(node_description, axes_vector, rank);
|
||||
return AxisSet{normalized_axes};
|
||||
}
|
||||
} // namespace ngraph
|
@ -15,17 +15,17 @@ NGRAPH_RTTI_DEFINITION(op::util::LogicalReduction, "LogicalReduction", 1);
|
||||
op::util::LogicalReduction::LogicalReduction() {}
|
||||
|
||||
op::util::LogicalReduction::LogicalReduction(const Output<Node>& arg, const AxisSet& reduction_axes)
|
||||
: Op({arg,
|
||||
: ReductionBase(arg,
|
||||
op::Constant::create(
|
||||
element::i64, Shape{reduction_axes.size()}, reduction_axes.to_vector())
|
||||
->output(0)})
|
||||
->output(0))
|
||||
{
|
||||
add_provenance_group_member(input_value(1).get_node_shared_ptr());
|
||||
}
|
||||
|
||||
op::util::LogicalReduction::LogicalReduction(const Output<Node>& arg,
|
||||
const Output<Node>& reduction_axes)
|
||||
: Op({arg, reduction_axes})
|
||||
: ReductionBase(arg, reduction_axes)
|
||||
{
|
||||
}
|
||||
|
||||
@ -54,59 +54,20 @@ void op::util::LogicalReduction::set_reduction_axes(const AxisSet& reduction_axe
|
||||
void op::util::LogicalReduction::validate_and_infer_types()
|
||||
{
|
||||
NGRAPH_OP_SCOPE(util_LogicalReduction_validate_and_infer_types);
|
||||
auto input_shape = get_input_partial_shape(0);
|
||||
auto input_rank = input_shape.rank();
|
||||
|
||||
PartialShape result_shape{PartialShape::dynamic()};
|
||||
const element::Type& data_et = get_input_element_type(0);
|
||||
const PartialShape& axes_shape = get_input_partial_shape(1);
|
||||
|
||||
NODE_VALIDATION_CHECK(
|
||||
this, data_et.compatible(element::boolean), "Element type of data input must be boolean.");
|
||||
|
||||
const Rank axes_rank = axes_shape.rank();
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
axes_rank.compatible(0) || axes_rank.compatible(1),
|
||||
"Axes input must be a scalar or 1D input. Got: ",
|
||||
axes_shape);
|
||||
|
||||
PartialShape result_shape = infer_reduction_output_shape(false);
|
||||
set_input_is_relevant_to_shape(1);
|
||||
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
get_input_element_type(0).compatible(element::boolean),
|
||||
"Input element type must be boolean.");
|
||||
|
||||
set_output_type(0, element::boolean, result_shape);
|
||||
|
||||
if (input_rank.is_dynamic())
|
||||
return;
|
||||
|
||||
if (const auto axes_const = get_constant_from_source(input_value(1)))
|
||||
{
|
||||
AxisSet reduction_axes;
|
||||
auto reduction_axes_val = axes_const->cast_vector<int64_t>();
|
||||
for (auto axis : reduction_axes_val)
|
||||
{
|
||||
try
|
||||
{
|
||||
axis = normalize_axis(this, axis, input_rank);
|
||||
}
|
||||
catch (const ngraph_error&)
|
||||
{
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
false,
|
||||
"Reduction axis (",
|
||||
axis,
|
||||
") is out of bounds ",
|
||||
"(argument shape: ",
|
||||
input_shape,
|
||||
", reduction axes: ",
|
||||
reduction_axes,
|
||||
")");
|
||||
}
|
||||
reduction_axes.insert(axis);
|
||||
}
|
||||
|
||||
std::vector<Dimension> dims;
|
||||
for (int64_t i = 0; i < input_rank.get_length(); i++)
|
||||
{
|
||||
if (reduction_axes.count(i) == 0)
|
||||
{
|
||||
dims.push_back(input_shape[i]);
|
||||
}
|
||||
}
|
||||
|
||||
result_shape = PartialShape(dims);
|
||||
}
|
||||
|
||||
set_output_type(0, element::boolean, result_shape);
|
||||
set_output_type(0, data_et, result_shape);
|
||||
}
|
||||
|
@ -32,63 +32,26 @@ bool ngraph::op::util::LogicalReductionKeepDims::visit_attributes(AttributeVisit
|
||||
void op::util::LogicalReductionKeepDims::validate_and_infer_types()
|
||||
{
|
||||
NGRAPH_OP_SCOPE(v0_util_LogicalReductionKeepDims_validate_and_infer_types);
|
||||
if (m_keep_dims)
|
||||
{
|
||||
const auto input_shape = get_input_partial_shape(0);
|
||||
const auto input_rank = input_shape.rank();
|
||||
PartialShape result_shape{PartialShape::dynamic(input_rank)};
|
||||
|
||||
set_input_is_relevant_to_shape(1);
|
||||
set_output_type(0, get_input_element_type(0), result_shape);
|
||||
const element::Type& data_et = get_input_element_type(0);
|
||||
const PartialShape& axes_shape = get_input_partial_shape(1);
|
||||
const element::Type& axes_et = get_input_element_type(1);
|
||||
|
||||
if (input_shape.is_dynamic())
|
||||
return;
|
||||
NODE_VALIDATION_CHECK(
|
||||
this, data_et.compatible(element::boolean), "Element type of data input must be boolean.");
|
||||
|
||||
if (auto axes_const = get_constant_from_source(input_value(1)))
|
||||
{
|
||||
AxisSet reduction_axes;
|
||||
auto reduction_axes_val = axes_const->cast_vector<int64_t>();
|
||||
for (auto axis : reduction_axes_val)
|
||||
{
|
||||
try
|
||||
{
|
||||
axis = normalize_axis(this, axis, input_rank);
|
||||
}
|
||||
catch (const ngraph_error&)
|
||||
{
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
false,
|
||||
"Reduction axis (",
|
||||
axis,
|
||||
") is out of bounds ",
|
||||
"(argument shape: ",
|
||||
input_shape,
|
||||
", reduction axes: ",
|
||||
reduction_axes,
|
||||
")");
|
||||
}
|
||||
reduction_axes.insert(axis);
|
||||
}
|
||||
axes_et.is_integral_number(),
|
||||
"Element type of axes input must be integer. Got: ",
|
||||
axes_et);
|
||||
|
||||
std::vector<Dimension> dims;
|
||||
for (int64_t i = 0; i < input_rank.get_length(); i++)
|
||||
{
|
||||
if (reduction_axes.count(i) == 0)
|
||||
{
|
||||
dims.push_back(input_shape[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
dims.emplace_back(Dimension{1});
|
||||
}
|
||||
}
|
||||
result_shape = PartialShape(dims);
|
||||
}
|
||||
const Rank axes_rank = axes_shape.rank();
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
axes_rank.compatible(0) || axes_rank.compatible(1),
|
||||
"Axes input must be a scalar or 1D input. Got: ",
|
||||
axes_shape);
|
||||
|
||||
set_output_type(0, get_input_element_type(0), result_shape);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogicalReduction::validate_and_infer_types();
|
||||
}
|
||||
PartialShape result_shape = infer_reduction_output_shape(m_keep_dims);
|
||||
set_input_is_relevant_to_shape(1);
|
||||
set_output_type(0, data_et, result_shape);
|
||||
}
|
||||
|
74
ngraph/core/src/op/util/reduction_base.cpp
Normal file
74
ngraph/core/src/op/util/reduction_base.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "ngraph/op/util/reduction_base.hpp"
|
||||
#include "itt.hpp"
|
||||
#include "ngraph/op/constant.hpp"
|
||||
#include "ngraph/validation_util.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
NGRAPH_RTTI_DEFINITION(op::util::ReductionBase, "ReductionBase", 0);
|
||||
|
||||
op::util::ReductionBase::ReductionBase() {}
|
||||
|
||||
op::util::ReductionBase::ReductionBase(const Output<Node>& arg, const Output<Node>& reduction_axes)
|
||||
: Op({arg, reduction_axes})
|
||||
{
|
||||
}
|
||||
|
||||
PartialShape op::util::ReductionBase::infer_reduction_output_shape(const bool keep_dims)
|
||||
{
|
||||
const PartialShape& data_ps = get_input_partial_shape(0);
|
||||
PartialShape result_ps{PartialShape::dynamic()};
|
||||
Rank data_rank = data_ps.rank();
|
||||
|
||||
if (data_rank.is_static() && keep_dims)
|
||||
{
|
||||
result_ps = PartialShape::dynamic(data_rank);
|
||||
}
|
||||
|
||||
const auto& axes = get_constant_from_source(input_value(1));
|
||||
if (data_rank.is_static() && axes)
|
||||
{
|
||||
AxisSet reduction_axes;
|
||||
auto reduction_axes_val = axes->cast_vector<int64_t>();
|
||||
for (auto axis : reduction_axes_val)
|
||||
{
|
||||
try
|
||||
{
|
||||
axis = normalize_axis(this, axis, data_rank);
|
||||
}
|
||||
catch (const ngraph_error&)
|
||||
{
|
||||
NODE_VALIDATION_CHECK(this,
|
||||
false,
|
||||
"Reduction axis (",
|
||||
axis,
|
||||
") is out of bounds ",
|
||||
"(argument shape: ",
|
||||
data_ps,
|
||||
", reduction axes: ",
|
||||
reduction_axes,
|
||||
")");
|
||||
}
|
||||
reduction_axes.insert(axis);
|
||||
}
|
||||
std::vector<Dimension> dims;
|
||||
for (int64_t i = 0; i < data_rank.get_length(); i++)
|
||||
{
|
||||
if (reduction_axes.count(i) == 0)
|
||||
{
|
||||
dims.push_back(data_ps[i]);
|
||||
}
|
||||
else if (keep_dims)
|
||||
{
|
||||
dims.emplace_back(Dimension{1});
|
||||
}
|
||||
}
|
||||
result_ps = PartialShape(dims);
|
||||
}
|
||||
return result_ps;
|
||||
}
|
@ -19,19 +19,6 @@ namespace ngraph
|
||||
{
|
||||
OutputVector global_average_pool(const Node& node)
|
||||
{
|
||||
auto data = node.get_ng_inputs()[0];
|
||||
auto data_rank = data.get_partial_shape().rank();
|
||||
|
||||
NGRAPH_CHECK(data_rank.is_static(),
|
||||
"The input data tensor's rank has to be known (static)");
|
||||
|
||||
auto data_rank_value = data_rank.get_length();
|
||||
|
||||
NGRAPH_CHECK(data_rank_value > 2,
|
||||
"The input data tensor's rank has to be greater than 2."
|
||||
"Provided data rank is: ",
|
||||
data_rank_value);
|
||||
|
||||
// Generate axes for reduce operation which contain all spatial dims indexes.
|
||||
// Examples:
|
||||
// Input shape: [N, C, H, W]
|
||||
@ -41,11 +28,22 @@ namespace ngraph
|
||||
// Input shape: [N, C, H, W, D]
|
||||
// Input spatial dimensions are H, W and D
|
||||
// Expected spatial dims indexes: [2, 3, 4]
|
||||
size_t data_spatial_rank = data_rank_value - 2;
|
||||
auto reduce_axes_vector = std::vector<std::int64_t>(data_spatial_rank);
|
||||
std::iota(reduce_axes_vector.begin(), reduce_axes_vector.end(), 2);
|
||||
auto reduce_axes = default_opset::Constant::create(
|
||||
element::i64, Shape{data_spatial_rank}, reduce_axes_vector);
|
||||
auto data = node.get_ng_inputs()[0];
|
||||
|
||||
const auto zero_node =
|
||||
default_opset::Constant::create(element::i64, Shape{}, {0});
|
||||
const auto one_node =
|
||||
default_opset::Constant::create(element::i64, Shape{}, {1});
|
||||
const auto two_node =
|
||||
default_opset::Constant::create(element::i64, Shape{}, {2});
|
||||
|
||||
const auto data_shape = std::make_shared<default_opset::ShapeOf>(data);
|
||||
const auto data_rank = std::make_shared<default_opset::ShapeOf>(data_shape);
|
||||
const auto data_rank_as_scalar =
|
||||
std::make_shared<default_opset::Squeeze>(data_rank);
|
||||
|
||||
const auto reduce_axes = std::make_shared<default_opset::Range>(
|
||||
two_node, data_rank_as_scalar, one_node, element::i64);
|
||||
|
||||
return {std::make_shared<default_opset::ReduceMean>(data, reduce_axes, true)};
|
||||
}
|
||||
|
@ -19,19 +19,6 @@ namespace ngraph
|
||||
{
|
||||
OutputVector global_max_pool(const Node& node)
|
||||
{
|
||||
auto data = node.get_ng_inputs()[0];
|
||||
auto data_rank = data.get_partial_shape().rank();
|
||||
|
||||
NGRAPH_CHECK(data_rank.is_static(),
|
||||
"The input data tensor's rank has to be known (static)");
|
||||
|
||||
auto data_rank_value = data_rank.get_length();
|
||||
|
||||
NGRAPH_CHECK(data_rank_value > 2,
|
||||
"The input data tensor's rank has to be greater than 2."
|
||||
"Provided data rank is: ",
|
||||
data_rank_value);
|
||||
|
||||
// Generate axes for reduce operation which contain all spatial dims indexes.
|
||||
// Examples:
|
||||
// Input shape: [N, C, H, W]
|
||||
@ -41,11 +28,22 @@ namespace ngraph
|
||||
// Input shape: [N, C, H, W, D]
|
||||
// Input spatial dimensions are H, W and D
|
||||
// Expected spatial dims indexes: [2, 3, 4]
|
||||
size_t data_spatial_rank = data_rank_value - 2;
|
||||
auto reduce_axes_vector = std::vector<std::int64_t>(data_spatial_rank);
|
||||
std::iota(reduce_axes_vector.begin(), reduce_axes_vector.end(), 2);
|
||||
auto reduce_axes = default_opset::Constant::create(
|
||||
element::i64, Shape{data_spatial_rank}, reduce_axes_vector);
|
||||
auto data = node.get_ng_inputs()[0];
|
||||
|
||||
const auto zero_node =
|
||||
default_opset::Constant::create(element::i64, Shape{}, {0});
|
||||
const auto one_node =
|
||||
default_opset::Constant::create(element::i64, Shape{}, {1});
|
||||
const auto two_node =
|
||||
default_opset::Constant::create(element::i64, Shape{}, {2});
|
||||
|
||||
const auto data_shape = std::make_shared<default_opset::ShapeOf>(data);
|
||||
const auto data_rank = std::make_shared<default_opset::ShapeOf>(data_shape);
|
||||
const auto data_rank_as_scalar =
|
||||
std::make_shared<default_opset::Squeeze>(data_rank);
|
||||
|
||||
const auto reduce_axes = std::make_shared<default_opset::Range>(
|
||||
two_node, data_rank_as_scalar, one_node, element::i64);
|
||||
|
||||
return {std::make_shared<default_opset::ReduceMax>(data, reduce_axes, true)};
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ set(SRC
|
||||
op_eval/non_zero.cpp
|
||||
op_eval/reduce_l1.cpp
|
||||
op_eval/reduce_l2.cpp
|
||||
op_eval/reduce_prod.cpp
|
||||
op_eval/reduce_sum.cpp
|
||||
op_eval/roi_align.cpp
|
||||
op_eval/roi_pooling.cpp
|
||||
op_eval/round.cpp
|
||||
@ -172,6 +174,13 @@ set(SRC
|
||||
type_prop/read_value.cpp
|
||||
type_prop/reduce_l1.cpp
|
||||
type_prop/reduce_l2.cpp
|
||||
type_prop/reduce_logical_and.cpp
|
||||
type_prop/reduce_logical_or.cpp
|
||||
type_prop/reduce_max.cpp
|
||||
type_prop/reduce_mean.cpp
|
||||
type_prop/reduce_min.cpp
|
||||
type_prop/reduce_prod.cpp
|
||||
type_prop/reduce_sum.cpp
|
||||
type_prop/reorg_yolo.cpp
|
||||
type_prop/reshape.cpp
|
||||
type_prop/result.cpp
|
||||
@ -188,6 +197,7 @@ set(SRC
|
||||
type_prop/scatter_nd_update.cpp
|
||||
type_prop/scatter_update.cpp
|
||||
type_prop/select.cpp
|
||||
type_prop/selu.cpp
|
||||
type_prop/shape_of.cpp
|
||||
type_prop/shuffle_channels.cpp
|
||||
type_prop/softmax.cpp
|
||||
@ -198,9 +208,6 @@ set(SRC
|
||||
type_prop/squared_difference.cpp
|
||||
type_prop/squeeze.cpp
|
||||
type_prop/swish.cpp
|
||||
type_prop/reduce_mean.cpp
|
||||
type_prop/reduce_prod.cpp
|
||||
type_prop/reduce_sum.cpp
|
||||
type_prop/ti.cpp
|
||||
type_prop/tile.cpp
|
||||
type_prop/top_k.cpp
|
||||
@ -265,8 +272,10 @@ set(SRC
|
||||
visitors/op/reverse_sequence.cpp
|
||||
visitors/op/rnn_cell.cpp
|
||||
visitors/op/roi_pooling.cpp
|
||||
visitors/op/selu.cpp
|
||||
visitors/op/shuffle_channels.cpp
|
||||
visitors/op/softmax.cpp
|
||||
visitors/op/space_to_batch.cpp
|
||||
visitors/op/space_to_depth.cpp
|
||||
visitors/op/split.cpp
|
||||
visitors/op/squared_difference.cpp
|
||||
@ -347,6 +356,7 @@ set(MULTI_TEST_SRC
|
||||
backend/constant.in.cpp
|
||||
backend/convert.in.cpp
|
||||
backend/convert_like.in.cpp
|
||||
backend/convolution_backprop.in.cpp
|
||||
backend/convolution.in.cpp
|
||||
backend/binary_convolution.in.cpp
|
||||
backend/clamp.in.cpp
|
||||
@ -430,12 +440,14 @@ set(MULTI_TEST_SRC
|
||||
backend/round.in.cpp
|
||||
backend/scatter_nd_update.in.cpp
|
||||
backend/select.in.cpp
|
||||
backend/selu.in.cpp
|
||||
backend/shape_of.in.cpp
|
||||
backend/sigmoid.in.cpp
|
||||
backend/sign.in.cpp
|
||||
backend/sin.in.cpp
|
||||
backend/sinh.in.cpp
|
||||
backend/softmax.in.cpp
|
||||
backend/space_to_batch.in.cpp
|
||||
backend/split.in.cpp
|
||||
backend/sqrt.in.cpp
|
||||
backend/squared_difference.in.cpp
|
||||
|
1221
ngraph/test/backend/convolution_backprop.in.cpp
Normal file
1221
ngraph/test/backend/convolution_backprop.in.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -80,95 +80,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_rows)
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{2, 12, 30}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_to_matrix_most_sig)
|
||||
{
|
||||
Shape shape_a{3, 3, 3};
|
||||
@ -283,31 +194,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_to_scalar)
|
||||
read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_2d_to_scalar_int32)
|
||||
{
|
||||
Shape shape_a{3, 3};
|
||||
@ -433,95 +319,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_rows)
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{2, 12, 30}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_to_matrix_most_sig)
|
||||
{
|
||||
Shape shape_a{3, 3, 3};
|
||||
@ -636,31 +433,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_to_scalar)
|
||||
read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_product_keep_2d_to_scalar_int32)
|
||||
{
|
||||
Shape shape_a{3, 3};
|
||||
|
@ -151,95 +151,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_rows)
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{3, 7, 11}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_matrix_most_sig)
|
||||
{
|
||||
Shape shape_a{3, 3, 3};
|
||||
@ -376,56 +287,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_to_scalar_int32)
|
||||
read_vector<int32_t>(result));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0, 0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_3d_eliminate_zero_dim_int32)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::i32, shape_a);
|
||||
Shape shape_rt{3, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::i32, shape_a);
|
||||
copy_data(a, vector<int32_t>{});
|
||||
auto result = backend->create_tensor(element::i32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<int32_t>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_EQ((vector<int32_t>{0, 0, 0, 0, 0, 0}), read_vector<int32_t>(result));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_5d_to_scalar)
|
||||
{
|
||||
Shape shape_a{3, 3, 3, 3, 3};
|
||||
@ -489,27 +350,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_2d_to_scalar_int8)
|
||||
EXPECT_EQ(std::vector<int8_t>{45}, read_vector<int8_t>(result));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_trivial_in_double)
|
||||
{
|
||||
Shape shape{4, 3};
|
||||
Shape rshape{3};
|
||||
auto A = make_shared<op::Parameter>(element::f64, shape);
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f64, shape);
|
||||
copy_data(a, vector<double>{12, 2, 10, 9, 8, 4, 6, 1, 5, 3, 11, 7});
|
||||
auto result = backend->create_tensor(element::f64, rshape);
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<double>{30, 22, 26}), read_vector<double>(result)));
|
||||
}
|
||||
|
||||
#if NGRAPH_INTERPRETER_ENABLE
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -548,39 +388,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_acc)
|
||||
}
|
||||
#endif
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_acc_double)
|
||||
{
|
||||
std::string backend_name = "${BACKEND_NAME}";
|
||||
if (backend_name == "INTERPRETER")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Shape shape_a{10, 10, 20, 300};
|
||||
auto A = make_shared<op::Parameter>(element::f64, shape_a);
|
||||
|
||||
Shape shape_rt{10};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{3}, vector<int32_t>{1, 2, 3});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
test::Uniform<double> rng(1000000000.0L, 1000000000.001L, 2112);
|
||||
vector<vector<double>> args;
|
||||
for (shared_ptr<op::Parameter> param : f->get_parameters())
|
||||
{
|
||||
vector<double> tensor_val(shape_size(param->get_shape()));
|
||||
rng.initialize(tensor_val);
|
||||
args.push_back(tensor_val);
|
||||
}
|
||||
|
||||
auto ref_func = clone_function(*f);
|
||||
auto bk_func = clone_function(*f);
|
||||
|
||||
auto ref_results = execute(ref_func, args, "INTERPRETER");
|
||||
auto bk_results = execute(bk_func, args, "${BACKEND_NAME}");
|
||||
|
||||
EXPECT_TRUE(test::all_close(ref_results.at(0), bk_results.at(0), 0.0, 1e-5));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_simple_float)
|
||||
{
|
||||
std::string backend_name = "${BACKEND_NAME}";
|
||||
@ -611,106 +418,8 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_simple_float)
|
||||
test::all_close_f(ref_results.at(0), bk_results.at(0), DEFAULT_FLOAT_TOLERANCE_BITS - 1));
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_stable_simple_double)
|
||||
{
|
||||
std::string backend_name = "${BACKEND_NAME}";
|
||||
if (backend_name == "INTERPRETER")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Shape shape_a{20};
|
||||
auto A = make_shared<op::Parameter>(element::f64, shape_a);
|
||||
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
vector<vector<double>> args;
|
||||
args.push_back(vector<double>{10000000000000000.0L,
|
||||
0.2L,
|
||||
0.3L,
|
||||
0.4L,
|
||||
0.5L,
|
||||
0.6L,
|
||||
0.7L,
|
||||
0.8L,
|
||||
0.9L,
|
||||
0.7L,
|
||||
0.9L,
|
||||
0.7L,
|
||||
0.3L,
|
||||
0.6L,
|
||||
0.8L,
|
||||
0.4L,
|
||||
0.6L,
|
||||
0.5L,
|
||||
0.8L,
|
||||
0.7L});
|
||||
|
||||
auto ref_func = clone_function(*f);
|
||||
auto bk_func = clone_function(*f);
|
||||
|
||||
auto ref_results = execute(ref_func, args, "INTERPRETER");
|
||||
auto bk_results = execute(bk_func, args, "${BACKEND_NAME}");
|
||||
|
||||
EXPECT_TRUE(test::all_close(ref_results.at(0), bk_results.at(0), 0.0, 2.0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_dynamic)
|
||||
{
|
||||
// Create a graph for f(x,axes:int32) = Sum(x,Convert<int64>(axes)).
|
||||
auto x = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
auto axes = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
|
||||
auto axes_i64 = make_shared<op::Convert>(axes, element::i64);
|
||||
|
||||
auto sum = make_shared<op::v1::ReduceSum>(x, axes_i64, false);
|
||||
ASSERT_TRUE(sum->get_output_partial_shape(0).rank().is_dynamic());
|
||||
|
||||
auto f = make_shared<Function>(NodeVector{sum}, ParameterVector{x, axes});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}", true);
|
||||
|
||||
auto ex = backend->compile(f);
|
||||
|
||||
auto t_r = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic());
|
||||
|
||||
std::vector<Shape> x_shapes{
|
||||
Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{5}, Shape{5}};
|
||||
std::vector<std::vector<int32_t>> axeses{{}, {0}, {1}, {0, 1}, {}, {0}};
|
||||
std::vector<std::vector<float>> inputs{{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5}};
|
||||
std::vector<Shape> expected_result_shapes{
|
||||
Shape{2, 3}, Shape{3}, Shape{2}, Shape{}, Shape{5}, Shape{}};
|
||||
std::vector<std::vector<float>> expected_results{
|
||||
{1, 2, 3, 4, 5, 6}, {5, 7, 9}, {6, 15}, {21}, {1, 2, 3, 4, 5}, {15}};
|
||||
|
||||
for (size_t i = 0; i < x_shapes.size(); i++)
|
||||
{
|
||||
auto t_x = backend->create_tensor(element::f32, x_shapes[i]);
|
||||
auto t_axes = backend->create_tensor(element::i32, Shape{axeses[i].size()});
|
||||
|
||||
copy_data(t_x, inputs[i]);
|
||||
copy_data(t_axes, axeses[i]);
|
||||
|
||||
ex->call_with_validate({t_r}, {t_x, t_axes});
|
||||
|
||||
ASSERT_EQ(t_r->get_shape(), expected_result_shapes[i]);
|
||||
|
||||
auto results = read_vector<float>(t_r);
|
||||
|
||||
ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS));
|
||||
}
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_inf)
|
||||
{
|
||||
Shape shape{7, 4};
|
||||
@ -874,95 +583,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_rows)
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{3, 7, 11}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_matrix_most_sig)
|
||||
{
|
||||
Shape shape_a{3, 3, 3};
|
||||
@ -1099,56 +719,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_to_scalar_int32)
|
||||
read_vector<int32_t>(result));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0, 0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_3d_eliminate_zero_dim_int32)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::i32, shape_a);
|
||||
Shape shape_rt{3, 1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::i32, shape_a);
|
||||
copy_data(a, vector<int32_t>{});
|
||||
auto result = backend->create_tensor(element::i32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<int32_t>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_EQ((vector<int32_t>{0, 0, 0, 0, 0, 0}), read_vector<int32_t>(result));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_5d_to_scalar)
|
||||
{
|
||||
Shape shape_a{3, 3, 3, 3, 3};
|
||||
@ -1212,27 +782,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_2d_to_scalar_int8)
|
||||
EXPECT_EQ(std::vector<int8_t>{45}, read_vector<int8_t>(result));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_trivial_in_double)
|
||||
{
|
||||
Shape shape{4, 3};
|
||||
Shape rshape{1, 3};
|
||||
auto A = make_shared<op::Parameter>(element::f64, shape);
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f64, shape);
|
||||
copy_data(a, vector<double>{12, 2, 10, 9, 8, 4, 6, 1, 5, 3, 11, 7});
|
||||
auto result = backend->create_tensor(element::f64, rshape);
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<double>{30, 22, 26}), read_vector<double>(result)));
|
||||
}
|
||||
|
||||
#if NGRAPH_INTERPRETER_ENABLE
|
||||
|
||||
#ifndef _WIN32
|
||||
@ -1271,38 +820,6 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_acc)
|
||||
}
|
||||
#endif
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_acc_double)
|
||||
{
|
||||
std::string backend_name = "${BACKEND_NAME}";
|
||||
if (backend_name == "INTERPRETER")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Shape shape_a{10, 10, 20, 300};
|
||||
auto A = make_shared<op::Parameter>(element::f64, shape_a);
|
||||
|
||||
Shape shape_rt{10, 1, 1, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{3}, vector<int32_t>{1, 2, 3});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
test::Uniform<double> rng(1000000000.0L, 1000000000.001L, 2112);
|
||||
vector<vector<double>> args;
|
||||
for (shared_ptr<op::Parameter> param : f->get_parameters())
|
||||
{
|
||||
vector<double> tensor_val(shape_size(param->get_shape()));
|
||||
rng.initialize(tensor_val);
|
||||
args.push_back(tensor_val);
|
||||
}
|
||||
|
||||
auto ref_func = clone_function(*f);
|
||||
auto bk_func = clone_function(*f);
|
||||
|
||||
auto ref_results = execute(ref_func, args, "INTERPRETER");
|
||||
auto bk_results = execute(bk_func, args, "${BACKEND_NAME}");
|
||||
|
||||
EXPECT_TRUE(test::all_close(ref_results.at(0), bk_results.at(0), 0.0, 1e-5));
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_simple_float)
|
||||
{
|
||||
@ -1334,106 +851,8 @@ NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_simple_float)
|
||||
test::all_close_f(ref_results.at(0), bk_results.at(0), DEFAULT_FLOAT_TOLERANCE_BITS - 1));
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_stable_simple_double)
|
||||
{
|
||||
std::string backend_name = "${BACKEND_NAME}";
|
||||
if (backend_name == "INTERPRETER")
|
||||
{
|
||||
return;
|
||||
}
|
||||
Shape shape_a{20};
|
||||
auto A = make_shared<op::Parameter>(element::f64, shape_a);
|
||||
|
||||
Shape shape_rt{1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
vector<vector<double>> args;
|
||||
args.push_back(vector<double>{10000000000000000.0L,
|
||||
0.2L,
|
||||
0.3L,
|
||||
0.4L,
|
||||
0.5L,
|
||||
0.6L,
|
||||
0.7L,
|
||||
0.8L,
|
||||
0.9L,
|
||||
0.7L,
|
||||
0.9L,
|
||||
0.7L,
|
||||
0.3L,
|
||||
0.6L,
|
||||
0.8L,
|
||||
0.4L,
|
||||
0.6L,
|
||||
0.5L,
|
||||
0.8L,
|
||||
0.7L});
|
||||
|
||||
auto ref_func = clone_function(*f);
|
||||
auto bk_func = clone_function(*f);
|
||||
|
||||
auto ref_results = execute(ref_func, args, "INTERPRETER");
|
||||
auto bk_results = execute(bk_func, args, "${BACKEND_NAME}");
|
||||
|
||||
EXPECT_TRUE(test::all_close(ref_results.at(0), bk_results.at(0), 0.0, 2.0));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_dynamic)
|
||||
{
|
||||
// Create a graph for f(x,axes:int32) = Sum(x,Convert<int64>(axes)).
|
||||
auto x = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
auto axes = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
|
||||
auto axes_i64 = make_shared<op::Convert>(axes, element::i64);
|
||||
|
||||
auto sum = make_shared<op::v1::ReduceSum>(x, axes_i64, true);
|
||||
ASSERT_TRUE(sum->get_output_partial_shape(0).rank().is_dynamic());
|
||||
|
||||
auto f = make_shared<Function>(NodeVector{sum}, ParameterVector{x, axes});
|
||||
|
||||
auto backend = runtime::Backend::create("${BACKEND_NAME}", true);
|
||||
|
||||
auto ex = backend->compile(f);
|
||||
|
||||
auto t_r = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic());
|
||||
|
||||
std::vector<Shape> x_shapes{
|
||||
Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{5}, Shape{5}};
|
||||
std::vector<std::vector<int32_t>> axeses{{}, {0}, {1}, {0, 1}, {}, {0}};
|
||||
std::vector<std::vector<float>> inputs{{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5}};
|
||||
std::vector<Shape> expected_result_shapes{
|
||||
Shape{2, 3}, Shape{1, 3}, Shape{2, 1}, Shape{1, 1}, Shape{5}, Shape{1}};
|
||||
std::vector<std::vector<float>> expected_results{
|
||||
{1, 2, 3, 4, 5, 6}, {5, 7, 9}, {6, 15}, {21}, {1, 2, 3, 4, 5}, {15}};
|
||||
|
||||
for (size_t i = 0; i < x_shapes.size(); i++)
|
||||
{
|
||||
auto t_x = backend->create_tensor(element::f32, x_shapes[i]);
|
||||
auto t_axes = backend->create_tensor(element::i32, Shape{axeses[i].size()});
|
||||
|
||||
copy_data(t_x, inputs[i]);
|
||||
copy_data(t_axes, axeses[i]);
|
||||
|
||||
ex->call_with_validate({t_r}, {t_x, t_axes});
|
||||
|
||||
ASSERT_EQ(t_r->get_shape(), expected_result_shapes[i]);
|
||||
|
||||
auto results = read_vector<float>(t_r);
|
||||
|
||||
ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS));
|
||||
}
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, reduce_sum_keep_inf)
|
||||
{
|
||||
Shape shape{7, 4};
|
||||
|
99
ngraph/test/backend/selu.in.cpp
Normal file
99
ngraph/test/backend/selu.in.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/engine/test_engines.hpp"
|
||||
#include "util/test_case.hpp"
|
||||
#include "util/test_control.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
static string s_manifest = "${MANIFEST}";
|
||||
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, selu_2Dfprop)
|
||||
{
|
||||
Shape rt_shape{2};
|
||||
Shape c_shape{1};
|
||||
element::Type et = element::f32;
|
||||
|
||||
auto input = make_shared<op::Parameter>(et, rt_shape);
|
||||
auto alpha = op::Constant::create(et, c_shape, {1.67326324});
|
||||
auto lambda = op::Constant::create(et, c_shape, {1.05070098});
|
||||
auto selu = make_shared<op::v0::Selu>(input, alpha, lambda);
|
||||
auto f = make_shared<Function>(selu, ParameterVector{input});
|
||||
|
||||
vector<float> input_data{-1, 3};
|
||||
vector<float> expected_out{-1.1113307, 3.152103};
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(f);
|
||||
test_case.add_input<float>(rt_shape, input_data);
|
||||
test_case.add_expected_output(rt_shape, expected_out);
|
||||
test_case.run();
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, selu_4Dfprop)
|
||||
{
|
||||
Shape in_shape{4};
|
||||
Shape c_shape{1};
|
||||
element::Type et = element::f32;
|
||||
|
||||
auto input = make_shared<op::Parameter>(et, in_shape);
|
||||
auto alpha = op::Constant::create(et, c_shape, {1.67326324});
|
||||
auto lambda = op::Constant::create(et, c_shape, {1.05070098});
|
||||
auto selu = make_shared<op::v0::Selu>(input, alpha, lambda);
|
||||
auto f = make_shared<Function>(selu, ParameterVector{input});
|
||||
|
||||
vector<float> in_vec{-1.0, 0.0, 1.0, 2.0};
|
||||
vector<float> out_vec{-1.1113307, 0., 1.050701, 2.101402};
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(f);
|
||||
test_case.add_input<float>(in_shape, in_vec);
|
||||
test_case.add_expected_output<float>(in_shape, out_vec);
|
||||
test_case.run_with_tolerance_as_fp(1e-4f);
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, selu_1Dfprop)
|
||||
{
|
||||
Shape in_shape{1};
|
||||
Shape c_shape{1};
|
||||
element::Type et = element::f32;
|
||||
|
||||
auto input = make_shared<op::Parameter>(et, in_shape);
|
||||
auto alpha = op::Constant::create(et, c_shape, {1.67326324});
|
||||
auto lambda = op::Constant::create(et, c_shape, {1.05070098});
|
||||
auto selu = make_shared<op::v0::Selu>(input, alpha, lambda);
|
||||
auto f = make_shared<Function>(selu, ParameterVector{input});
|
||||
|
||||
vector<float> in_vec{112.0};
|
||||
vector<float> out_vec{117.67851};
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(f);
|
||||
test_case.add_input<float>(in_shape, in_vec);
|
||||
test_case.add_expected_output<float>(in_shape, out_vec);
|
||||
test_case.run_with_tolerance_as_fp(1e-4f);
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, selu_3Dfprop_negative)
|
||||
{
|
||||
Shape in_shape{3};
|
||||
Shape c_shape{1};
|
||||
element::Type et = element::f32;
|
||||
|
||||
auto input = make_shared<op::Parameter>(et, in_shape);
|
||||
auto alpha = op::Constant::create(et, c_shape, {1.67326324});
|
||||
auto lambda = op::Constant::create(et, c_shape, {1.05070098});
|
||||
auto selu = make_shared<op::v0::Selu>(input, alpha, lambda);
|
||||
auto f = make_shared<Function>(selu, ParameterVector{input});
|
||||
|
||||
vector<float> in_vec{-3.0, -12.5, -7.0};
|
||||
vector<float> out_vec{-1.6705687, -1.7580928, -1.7564961};
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(f);
|
||||
test_case.add_input<float>(in_shape, in_vec);
|
||||
test_case.add_expected_output<float>(in_shape, out_vec);
|
||||
test_case.run_with_tolerance_as_fp(1e-4f);
|
||||
}
|
115
ngraph/test/backend/space_to_batch.in.cpp
Normal file
115
ngraph/test/backend/space_to_batch.in.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/engine/test_engines.hpp"
|
||||
#include "util/test_case.hpp"
|
||||
#include "util/test_control.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
static string s_manifest = "${MANIFEST}";
|
||||
using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME});
|
||||
|
||||
static void SpaceToBatchTest(const std::vector<float>& inputs,
|
||||
const Shape inputs_shape,
|
||||
const std::vector<int64_t>& block_shapes,
|
||||
const Shape blocks_shape,
|
||||
const std::vector<int64_t>& pads_begins,
|
||||
const std::vector<int64_t>& pads_ends,
|
||||
const Shape pads_shape,
|
||||
const std::vector<float>& outputs,
|
||||
const Shape outputs_shape)
|
||||
{
|
||||
auto inputs_param = make_shared<op::Parameter>(element::f32, inputs_shape);
|
||||
auto block_shapes_param = make_shared<op::Constant>(element::i64, blocks_shape, block_shapes);
|
||||
auto pads_begins_param = make_shared<op::Constant>(element::i64, pads_shape, pads_begins);
|
||||
auto pads_ends_param = make_shared<op::Constant>(element::i64, pads_shape, pads_ends);
|
||||
|
||||
auto space_to_batch = make_shared<op::v1::SpaceToBatch>(
|
||||
inputs_param, block_shapes_param, pads_begins_param, pads_ends_param);
|
||||
auto f = make_shared<Function>(space_to_batch, ParameterVector{inputs_param});
|
||||
|
||||
auto test_case = test::TestCase<TestEngine>(f);
|
||||
test_case.add_input<float>(inputs);
|
||||
test_case.add_expected_output<float>(outputs_shape, outputs);
|
||||
test_case.run();
|
||||
}
|
||||
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, space_to_batch_4D)
|
||||
{
|
||||
const Shape inputs_shape{1, 1, 2, 2};
|
||||
const std::vector<float> inputs{1.0f, 1.0f,
|
||||
1.0f, 1.0f};
|
||||
|
||||
const Shape blocks_shape{4};
|
||||
const std::vector<int64_t> block_shapes{1, 1, 1, 1};
|
||||
|
||||
const Shape pads_shape{4};
|
||||
const std::vector<int64_t> pads_begins{0, 0 ,0, 0};
|
||||
const std::vector<int64_t> pads_ends{0, 0, 0, 0};
|
||||
|
||||
const Shape outputs_shape{1, 1, 2, 2};
|
||||
const std::vector<float> outputs{1.0f, 1.0f,
|
||||
1.0f, 1.0f};
|
||||
|
||||
|
||||
SpaceToBatchTest(inputs, inputs_shape, block_shapes, blocks_shape, pads_begins,
|
||||
pads_ends, pads_shape, outputs, outputs_shape);
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, space_to_batch_5D)
|
||||
{
|
||||
const Shape inputs_shape{1, 1, 3, 2, 1};
|
||||
const std::vector<float> inputs{1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f};
|
||||
|
||||
const Shape blocks_shape{5};
|
||||
const std::vector<int64_t> block_shapes{1, 1, 3, 2, 2};
|
||||
|
||||
const Shape pads_shape{5};
|
||||
const std::vector<int64_t> pads_begins{0, 0 ,1, 0, 3};
|
||||
const std::vector<int64_t> pads_ends{0, 0, 2, 0, 0};
|
||||
|
||||
const Shape outputs_shape{12, 1, 2, 1, 2};
|
||||
const std::vector<float> outputs{0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f};
|
||||
|
||||
|
||||
SpaceToBatchTest(inputs, inputs_shape, block_shapes, blocks_shape, pads_begins,
|
||||
pads_ends, pads_shape, outputs, outputs_shape);
|
||||
}
|
||||
|
||||
NGRAPH_TEST(${BACKEND_NAME}, space_to_batch_4x4)
|
||||
{
|
||||
const Shape inputs_shape{1, 1, 4, 4};
|
||||
const std::vector<float> inputs{1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
const Shape blocks_shape{4};
|
||||
const std::vector<int64_t> block_shapes{1, 1, 1, 1};
|
||||
|
||||
const Shape pads_shape{4};
|
||||
const std::vector<int64_t> pads_begins{0, 0, 1, 0};
|
||||
const std::vector<int64_t> pads_ends{0, 0, 0, 0};
|
||||
|
||||
const Shape outputs_shape{1, 1, 5, 4};
|
||||
const std::vector<float> outputs{0.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f};
|
||||
|
||||
SpaceToBatchTest(inputs, inputs_shape, block_shapes, blocks_shape, pads_begins,
|
||||
pads_ends, pads_shape, outputs, outputs_shape);
|
||||
}
|
244
ngraph/test/op_eval/reduce_prod.cpp
Normal file
244
ngraph/test/op_eval/reduce_prod.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/test_control.hpp"
|
||||
#include "util/all_close.hpp"
|
||||
#include "util/all_close_f.hpp"
|
||||
#include "util/ndarray.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
static string s_manifest = "${MANIFEST}";
|
||||
|
||||
TEST(op_eval, reduce_product_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_keep_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_keep_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_keep_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_keep_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_product_keep_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceProd>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1}), read_vector<float>(result)));
|
||||
}
|
395
ngraph/test/op_eval/reduce_sum.cpp
Normal file
395
ngraph/test/op_eval/reduce_sum.cpp
Normal file
@ -0,0 +1,395 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/test_control.hpp"
|
||||
#include "util/all_close.hpp"
|
||||
#include "util/all_close_f.hpp"
|
||||
#include "util/ndarray.hpp"
|
||||
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
static string s_manifest = "${MANIFEST}";
|
||||
|
||||
TEST(op_eval, reduce_sum_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
|
||||
TEST(op_eval, reduce_sum_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0, 0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_3d_eliminate_zero_dim_int32)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::i32, shape_a);
|
||||
Shape shape_rt{3, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, false), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::i32, shape_a);
|
||||
copy_data(a, vector<int32_t>{});
|
||||
auto result = backend->create_tensor(element::i32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<int32_t>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_EQ((vector<int32_t>{0, 0, 0, 0, 0, 0}), read_vector<int32_t>(result));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_dynamic)
|
||||
{
|
||||
// Create a graph for f(x,axes:int32) = Sum(x,Convert<int64>(axes)).
|
||||
auto x = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
auto axes = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
|
||||
auto axes_i64 = make_shared<op::Convert>(axes, element::i64);
|
||||
|
||||
auto sum = make_shared<op::v1::ReduceSum>(x, axes_i64, false);
|
||||
ASSERT_TRUE(sum->get_output_partial_shape(0).rank().is_dynamic());
|
||||
|
||||
auto f = make_shared<Function>(NodeVector{sum}, ParameterVector{x, axes});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER", true);
|
||||
|
||||
auto ex = backend->compile(f);
|
||||
|
||||
auto t_r = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic());
|
||||
|
||||
std::vector<Shape> x_shapes{
|
||||
Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{5}, Shape{5}};
|
||||
std::vector<std::vector<int32_t>> axeses{{}, {0}, {1}, {0, 1}, {}, {0}};
|
||||
std::vector<std::vector<float>> inputs{{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5}};
|
||||
std::vector<Shape> expected_result_shapes{
|
||||
Shape{2, 3}, Shape{3}, Shape{2}, Shape{}, Shape{5}, Shape{}};
|
||||
std::vector<std::vector<float>> expected_results{
|
||||
{1, 2, 3, 4, 5, 6}, {5, 7, 9}, {6, 15}, {21}, {1, 2, 3, 4, 5}, {15}};
|
||||
|
||||
for (size_t i = 0; i < x_shapes.size(); i++)
|
||||
{
|
||||
auto t_x = backend->create_tensor(element::f32, x_shapes[i]);
|
||||
auto t_axes = backend->create_tensor(element::i32, Shape{axeses[i].size()});
|
||||
|
||||
copy_data(t_x, inputs[i]);
|
||||
copy_data(t_axes, axeses[i]);
|
||||
|
||||
ex->call_with_validate({t_r}, {t_x, t_axes});
|
||||
|
||||
ASSERT_EQ(t_r->get_shape(), expected_result_shapes[i]);
|
||||
|
||||
auto results = read_vector<float>(t_r);
|
||||
|
||||
ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_matrix_rows_zero)
|
||||
{
|
||||
Shape shape_a{3, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_matrix_cols_zero)
|
||||
{
|
||||
// Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
|
||||
Shape shape_a{0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3, 3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_vector_zero)
|
||||
{
|
||||
Shape shape_a{0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 0);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_matrix_to_scalar_zero_by_zero)
|
||||
{
|
||||
Shape shape_a{0, 0};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{1, 1};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{2}, vector<int32_t>{0, 1});
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
copy_data(result, vector<float>({3}));
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_3d_eliminate_zero_dim)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::f32, shape_a);
|
||||
Shape shape_rt{3, 1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::f32, shape_a);
|
||||
copy_data(a, vector<float>{});
|
||||
auto result = backend->create_tensor(element::f32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_TRUE(test::all_close_f((vector<float>{0, 0, 0, 0, 0, 0}), read_vector<float>(result)));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_3d_eliminate_zero_dim_int32)
|
||||
{
|
||||
Shape shape_a{3, 0, 2};
|
||||
auto A = make_shared<op::Parameter>(element::i32, shape_a);
|
||||
Shape shape_rt{3, 1, 2};
|
||||
auto axes = make_shared<op::Constant>(element::i32, Shape{}, 1);
|
||||
auto f =
|
||||
make_shared<Function>(make_shared<op::v1::ReduceSum>(A, axes, true), ParameterVector{A});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER");
|
||||
|
||||
// Create some tensors for input/output
|
||||
auto a = backend->create_tensor(element::i32, shape_a);
|
||||
copy_data(a, vector<int32_t>{});
|
||||
auto result = backend->create_tensor(element::i32, shape_rt);
|
||||
|
||||
// Overwrite the initial result vector to make sure we're not just coincidentally getting the
|
||||
// right value.
|
||||
copy_data(result, vector<int32_t>{2112, 2112, 2112, 2112, 2112, 2112});
|
||||
|
||||
auto handle = backend->compile(f);
|
||||
handle->call_with_validate({result}, {a});
|
||||
EXPECT_EQ((vector<int32_t>{0, 0, 0, 0, 0, 0}), read_vector<int32_t>(result));
|
||||
}
|
||||
|
||||
TEST(op_eval, reduce_sum_keep_dynamic)
|
||||
{
|
||||
// Create a graph for f(x,axes:int32) = Sum(x,Convert<int64>(axes)).
|
||||
auto x = make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
auto axes = make_shared<op::Parameter>(element::i32, PartialShape{Dimension::dynamic()});
|
||||
auto axes_i64 = make_shared<op::Convert>(axes, element::i64);
|
||||
|
||||
auto sum = make_shared<op::v1::ReduceSum>(x, axes_i64, true);
|
||||
ASSERT_TRUE(sum->get_output_partial_shape(0).rank().is_dynamic());
|
||||
|
||||
auto f = make_shared<Function>(NodeVector{sum}, ParameterVector{x, axes});
|
||||
|
||||
auto backend = runtime::Backend::create("INTERPRETER", true);
|
||||
|
||||
auto ex = backend->compile(f);
|
||||
|
||||
auto t_r = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic());
|
||||
|
||||
std::vector<Shape> x_shapes{
|
||||
Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{2, 3}, Shape{5}, Shape{5}};
|
||||
std::vector<std::vector<int32_t>> axeses{{}, {0}, {1}, {0, 1}, {}, {0}};
|
||||
std::vector<std::vector<float>> inputs{{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5, 6},
|
||||
{1, 2, 3, 4, 5},
|
||||
{1, 2, 3, 4, 5}};
|
||||
std::vector<Shape> expected_result_shapes{
|
||||
Shape{2, 3}, Shape{1, 3}, Shape{2, 1}, Shape{1, 1}, Shape{5}, Shape{1}};
|
||||
std::vector<std::vector<float>> expected_results{
|
||||
{1, 2, 3, 4, 5, 6}, {5, 7, 9}, {6, 15}, {21}, {1, 2, 3, 4, 5}, {15}};
|
||||
|
||||
for (size_t i = 0; i < x_shapes.size(); i++)
|
||||
{
|
||||
auto t_x = backend->create_tensor(element::f32, x_shapes[i]);
|
||||
auto t_axes = backend->create_tensor(element::i32, Shape{axeses[i].size()});
|
||||
|
||||
copy_data(t_x, inputs[i]);
|
||||
copy_data(t_axes, axeses[i]);
|
||||
|
||||
ex->call_with_validate({t_r}, {t_x, t_axes});
|
||||
|
||||
ASSERT_EQ(t_r->get_shape(), expected_result_shapes[i]);
|
||||
|
||||
auto results = read_vector<float>(t_r);
|
||||
|
||||
ASSERT_TRUE(test::all_close_f(results, expected_results[i], MIN_FLOAT_TOLERANCE_BITS));
|
||||
}
|
||||
}
|
@ -368,36 +368,18 @@ any_2x0_to_scalar
|
||||
all_trivial
|
||||
all_2x0_to_scalar
|
||||
all_dynamic
|
||||
reduce_sum_keep_dynamic
|
||||
reduce_sum_keep_stable_simple_double
|
||||
reduce_sum_keep_stable_acc_double
|
||||
reduce_sum_keep_stable_acc
|
||||
reduce_sum_keep_3d_eliminate_zero_dim
|
||||
reduce_sum_keep_vector_zero
|
||||
reduce_sum_keep_matrix_rows_zero
|
||||
reduce_sum_dynamic
|
||||
reduce_sum_3d_eliminate_zero_dim_int32
|
||||
reduce_sum_keep_3d_eliminate_zero_dim_int32
|
||||
reduce_sum_keep_trivial_in_double
|
||||
reduce_sum_3d_eliminate_zero_dim
|
||||
reduce_sum_matrix_to_scalar_zero_by_zero
|
||||
reduce_sum_vector_zero
|
||||
reduce_sum_matrix_cols_zero
|
||||
reduce_sum_matrix_rows_zero
|
||||
reduce_sum_keep_matrix_to_scalar_zero_by_zero
|
||||
reduce_sum_keep_matrix_cols_zero
|
||||
reduce_product_matrix_columns
|
||||
|
||||
# Reduce ops disabled/accuracy: 56520
|
||||
# disabled reference implementation
|
||||
reduce_sum_keep_2d_to_scalar_int8
|
||||
reduce_sum_2d_to_scalar_int8
|
||||
reduce_product_to_scalar_int8
|
||||
reduce_product_keep_to_scalar_int8
|
||||
# accuracy
|
||||
reduce_sum_keep_stable_acc
|
||||
reduce_sum_keep_2d_to_scalar_int8
|
||||
reduce_sum_keep_3d_to_scalar_int32
|
||||
reduce_sum_keep_large_1d_to_scalar
|
||||
reduce_sum_stable_simple_double
|
||||
reduce_sum_stable_acc_double
|
||||
reduce_sum_stable_acc
|
||||
reduce_sum_trivial_in_double
|
||||
reduce_sum_2d_to_scalar_int8
|
||||
reduce_sum_3d_to_scalar_int32
|
||||
reduce_sum_large_1d_to_scalar
|
||||
|
||||
@ -478,17 +460,6 @@ onnx_dyn_shapes_model_tile_static
|
||||
gather_4d_indices_axis_0_uint8
|
||||
tensor_constant_with_op
|
||||
constant_equality_bool
|
||||
reduce_product_matrix_rows
|
||||
reduce_product_3d_to_matrix_most_sig
|
||||
reduce_product_3d_to_matrix_least_sig
|
||||
reduce_product_keep_matrix_columns
|
||||
reduce_product_keep_matrix_rows
|
||||
reduce_product_keep_3d_to_matrix_most_sig
|
||||
reduce_product_keep_3d_to_matrix_least_sig
|
||||
reduce_product_matrix_columns_dynamic
|
||||
reduce_product_matrix_rows_dynamic
|
||||
reduce_product_keep_matrix_columns_dynamic
|
||||
reduce_product_keep_matrix_rows_dynamic
|
||||
reduce_min_matrix_columns
|
||||
reduce_min_matrix_rows
|
||||
reduce_min_matrix_rows_int32
|
||||
@ -505,18 +476,6 @@ reduce_min_keep_matrix_columns_dynamic
|
||||
reduce_min_keep_matrix_rows_dynamic
|
||||
|
||||
# zero dimension / result mismatch
|
||||
reduce_product_matrix_rows_zero
|
||||
reduce_product_matrix_cols_zero
|
||||
reduce_product_vector_zero
|
||||
reduce_product_matrix_to_scalar_zero_by_zero
|
||||
reduce_product_3d_eliminate_zero_dim
|
||||
reduce_product_to_scalar_int8
|
||||
reduce_product_keep_matrix_rows_zero
|
||||
reduce_product_keep_matrix_cols_zero
|
||||
reduce_product_keep_vector_zero
|
||||
reduce_product_keep_matrix_to_scalar_zero_by_zero
|
||||
reduce_product_keep_3d_eliminate_zero_dim
|
||||
reduce_product_keep_to_scalar_int8
|
||||
reduce_min_to_scalar_int8
|
||||
reduce_min_matrix_rows_zero
|
||||
reduce_min_matrix_cols_zero
|
||||
|
@ -283,7 +283,8 @@ namespace
|
||||
op->get_dilations(),
|
||||
op->get_pads_begin(),
|
||||
op->get_pads_end(),
|
||||
op->get_strides());
|
||||
op->get_strides(),
|
||||
op->get_output_padding());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ fake_quantize_pdpd
|
||||
INTERPRETER.onnx_model_quant_conv_linear
|
||||
INTERPRETER.onnx_top_k_opset_10
|
||||
|
||||
# Failed in ubuntu18 i386
|
||||
reduce_sum_large_1d_to_scalar
|
||||
reduce_sum_keep_large_1d_to_scalar
|
||||
|
||||
@ -31,11 +32,8 @@ INTERPRETER.onnx_model_matmul_integer_4d_no_zero_point
|
||||
# Disabled tests for disabled reference implementations
|
||||
INTERPRETER.onnx_dyn_shapes_expand_uint16_dyn_shape
|
||||
INTERPRETER.sum_2d_to_scalar_int8
|
||||
INTERPRETER.sum_trivial_in_double
|
||||
INTERPRETER.reduce_sum_2d_to_scalar_int8
|
||||
INTERPRETER.reduce_sum_trivial_in_double
|
||||
INTERPRETER.reduce_sum_keep_2d_to_scalar_int8
|
||||
INTERPRETER.reduce_sum_keep_trivial_in_double
|
||||
INTERPRETER.reduce_product_to_scalar_int8
|
||||
INTERPRETER.reduce_product_keep_to_scalar_int8
|
||||
INTERPRETER.reduce_min_to_scalar_int8
|
||||
|
@ -2,47 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
TEST(type_prop, reduce_l1_v4_axis_out_of_range)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{2, 3});
|
||||
try
|
||||
{
|
||||
auto reduce_sum = make_shared<op::v4::ReduceL1>(arg, axes);
|
||||
// Should have thrown, so fail if it didn't
|
||||
FAIL() << "Incorrect axes values exception not thrown";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Reduction axis ("));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_l1_v4_shape_if_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v4::ReduceL1>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3, 1, 1}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_l1_v4_shape_if_not_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = false;
|
||||
auto reduce_prod = make_shared<op::v4::ReduceL1>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3}));
|
||||
}
|
||||
using Type = ::testing::Types<op::v4::ReduceL1>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_l1, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_l1_et, ReduceArithmeticTest, Type);
|
||||
|
@ -2,47 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
TEST(type_prop, reduce_l2_v4_axis_out_of_range)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{2, 3});
|
||||
try
|
||||
{
|
||||
auto reduce_sum = make_shared<op::v4::ReduceL2>(arg, axes);
|
||||
// Should have thrown, so fail if it didn't
|
||||
FAIL() << "Incorrect axes values exception not thrown";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Reduction axis ("));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_l2_v4_shape_if_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v4::ReduceL2>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3, 1, 1}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_l2_v4_shape_if_not_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = false;
|
||||
auto reduce_prod = make_shared<op::v4::ReduceL2>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3}));
|
||||
}
|
||||
using Type = ::testing::Types<op::v4::ReduceL2>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_l2, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_l2_et, ReduceArithmeticTest, Type);
|
||||
|
9
ngraph/test/type_prop/reduce_logical_and.cpp
Normal file
9
ngraph/test/type_prop/reduce_logical_and.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using Type = ::testing::Types<op::v1::ReduceLogicalAnd>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_logical_and, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_logical_and_et, ReduceLogicalTest, Type);
|
9
ngraph/test/type_prop/reduce_logical_or.cpp
Normal file
9
ngraph/test/type_prop/reduce_logical_or.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using Type = ::testing::Types<op::v1::ReduceLogicalOr>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_logical_or, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_logical_or_et, ReduceLogicalTest, Type);
|
9
ngraph/test/type_prop/reduce_max.cpp
Normal file
9
ngraph/test/type_prop/reduce_max.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using Type = ::testing::Types<op::v1::ReduceMax>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_max, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_max_et, ReduceArithmeticTest, Type);
|
@ -2,71 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
TEST(type_prop, reduce_mean_v1_axis_out_of_range)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{2, 3});
|
||||
try
|
||||
{
|
||||
auto reduce_sum = make_shared<op::v1::ReduceMean>(arg, axes);
|
||||
|
||||
// Should have thrown, so fail if it didn't
|
||||
FAIL() << "Incorrect axes values exception not thrown";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Reduction axis ("));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_mean_v1_shape_if_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceMean>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3, 1, 1}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_mean_v1_shape_if_not_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = false;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceMean>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_mean_dynamic_shape)
|
||||
{
|
||||
auto arg =
|
||||
make_shared<op::Parameter>(element::f32, PartialShape{3, 4, 5, Dimension::dynamic()});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceMean>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(
|
||||
PartialShape{3, 1, 1, Dimension::dynamic()}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_mean_reduce_dynamic_shape)
|
||||
{
|
||||
auto arg =
|
||||
make_shared<op::Parameter>(element::f32, PartialShape{3, 4, 5, Dimension::dynamic()});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 3});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceMean>(arg, axes, keep_dims);
|
||||
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(
|
||||
PartialShape{3, 1, 5, Dimension::dynamic()}));
|
||||
}
|
||||
using Type = ::testing::Types<op::v1::ReduceMean>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_mean, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_mean_et, ReduceArithmeticTest, Type);
|
||||
|
9
ngraph/test/type_prop/reduce_min.cpp
Normal file
9
ngraph/test/type_prop/reduce_min.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using Type = ::testing::Types<op::v1::ReduceMin>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_min, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_min_et, ReduceArithmeticTest, Type);
|
388
ngraph/test/type_prop/reduce_ops.hpp
Normal file
388
ngraph/test/type_prop/reduce_ops.hpp
Normal file
@ -0,0 +1,388 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
struct ReduceParams
|
||||
{
|
||||
PartialShape data_ps;
|
||||
element::Type data_et;
|
||||
Shape axes_ps;
|
||||
std::vector<int64_t> axes;
|
||||
element::Type axes_et;
|
||||
bool keep_dims;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
static std::shared_ptr<Node> makeReduceOp(const ReduceParams& p, bool axes_as_param = false)
|
||||
{
|
||||
auto in_data = make_shared<op::Parameter>(p.data_et, p.data_ps);
|
||||
shared_ptr<Node> in_axes;
|
||||
if (axes_as_param)
|
||||
{
|
||||
in_axes = make_shared<op::Parameter>(p.axes_et, p.axes_ps);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (shape_size(p.axes_ps) != p.axes.size())
|
||||
{
|
||||
throw ngraph_error("Axes shape does not match with axes elements");
|
||||
}
|
||||
in_axes = make_shared<op::Constant>(p.axes_et, p.axes_ps, p.axes);
|
||||
}
|
||||
return make_shared<T>(in_data, in_axes, p.keep_dims);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
class ReduceTest : public testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TYPED_TEST_CASE_P(ReduceTest);
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_basic_shape_infer)
|
||||
{
|
||||
PartialShape data_ps{3, 4, 5};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{1, 2};
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
PartialShape out_ps{3};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_basic_shape_infer_keep_dims)
|
||||
{
|
||||
PartialShape data_ps{3, 4, 5};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{1, 2};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
PartialShape out_ps{3, 1, 1};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_basic_shape_infer_scalar_axis)
|
||||
{
|
||||
PartialShape data_ps{3, 4, 5};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{1};
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
PartialShape out_ps{3, 5};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_basic_shape_infer_axes_as_param)
|
||||
{
|
||||
PartialShape data_ps{3, 4, 5};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i32;
|
||||
std::vector<int64_t> axes;
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
PartialShape out_ps{PartialShape::dynamic()};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
bool axes_as_param = true;
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params, axes_as_param);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_dynamic_shape_reduced_axes_static)
|
||||
{
|
||||
PartialShape data_ps{3, 4, 5, Dimension::dynamic()};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{1, 2};
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
PartialShape out_ps{3, Dimension::dynamic()};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_dynamic_shape_reduced_axes_static_keep_dims)
|
||||
{
|
||||
PartialShape data_ps{3, 4, 5, Dimension::dynamic()};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{1, 2};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
PartialShape out_ps{3, 1, 1, Dimension::dynamic()};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_dynamic_shape_reduced_axes_not_static)
|
||||
{
|
||||
PartialShape data_ps{Dimension::dynamic(), 4, 5, Dimension::dynamic()};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{2, 3};
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
PartialShape out_ps{Dimension::dynamic(), 4};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_dynamic_shape_reduced_axes_not_static_keep_dims)
|
||||
{
|
||||
PartialShape data_ps{Dimension::dynamic(), 4, 5, Dimension::dynamic()};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{2, 3};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
PartialShape out_ps{Dimension::dynamic(), 4, 1, 1};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_dynamic_shape_data)
|
||||
{
|
||||
PartialShape data_ps{PartialShape::dynamic()};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{1, 2};
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
PartialShape out_ps{PartialShape::dynamic()};
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
ASSERT_TRUE(reduce_op->get_output_partial_shape(0).same_scheme(out_ps));
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_invalid_axis_out_of_range)
|
||||
{
|
||||
PartialShape data_ps{1, 2, 3};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{2, 3};
|
||||
|
||||
bool keep_dims = false;
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
try
|
||||
{
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
FAIL() << "Invalid axes values not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "Reduction axis (");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Axes input values validation check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_invalid_axes_shape)
|
||||
{
|
||||
PartialShape data_ps{1, 2, 3};
|
||||
element::Type data_et = element::dynamic;
|
||||
|
||||
Shape axes_ps{2, 1};
|
||||
element::Type axes_et = element::i64;
|
||||
std::vector<int64_t> axes{0, 1};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
try
|
||||
{
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
FAIL() << "Invalid shape of axes input not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "Axes input must be a scalar or 1D input.");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Axes input shape validation check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TYPED_TEST_P(ReduceTest, reduce_invalid_axes_et)
|
||||
{
|
||||
element::Type data_et = element::dynamic;
|
||||
PartialShape data_ps{1, 2, 3};
|
||||
|
||||
element::Type axes_et = element::f32;
|
||||
Shape axes_ps{2};
|
||||
std::vector<int64_t> axes{0, 1};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
try
|
||||
{
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
FAIL() << "Invalid element type of axes input not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "Element type of axes input must be integer.");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Axes input element type validation check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(
|
||||
ReduceTest,
|
||||
reduce_basic_shape_infer,
|
||||
reduce_basic_shape_infer_keep_dims,
|
||||
reduce_basic_shape_infer_scalar_axis,
|
||||
reduce_basic_shape_infer_axes_as_param,
|
||||
reduce_dynamic_shape_data,
|
||||
reduce_dynamic_shape_reduced_axes_static,
|
||||
reduce_dynamic_shape_reduced_axes_static_keep_dims,
|
||||
reduce_dynamic_shape_reduced_axes_not_static,
|
||||
reduce_dynamic_shape_reduced_axes_not_static_keep_dims,
|
||||
reduce_invalid_axis_out_of_range,
|
||||
reduce_invalid_axes_shape,
|
||||
reduce_invalid_axes_et);
|
||||
|
||||
template<class T>
|
||||
class ReduceArithmeticTest : public testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TYPED_TEST_CASE_P(ReduceArithmeticTest);
|
||||
|
||||
TYPED_TEST_P(ReduceArithmeticTest, reduce_arithmetic_invalid_data_et)
|
||||
{
|
||||
element::Type data_et = element::boolean;
|
||||
PartialShape data_ps{1, 2, 3};
|
||||
|
||||
element::Type axes_et = element::i32;
|
||||
Shape axes_ps{2};
|
||||
std::vector<int64_t> axes{0, 1};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
try
|
||||
{
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
FAIL() << "Invalid element type of data input not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "Element type of data input must be numeric.");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Data input element type validation check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(
|
||||
ReduceArithmeticTest,
|
||||
reduce_arithmetic_invalid_data_et);
|
||||
|
||||
template<class T>
|
||||
class ReduceLogicalTest : public testing::Test
|
||||
{
|
||||
};
|
||||
|
||||
TYPED_TEST_CASE_P(ReduceLogicalTest);
|
||||
|
||||
TYPED_TEST_P(ReduceLogicalTest, reduce_logical_invalid_data_et)
|
||||
{
|
||||
std::vector<element::Type> element_types{
|
||||
element::f32,
|
||||
element::i32,
|
||||
element::u32};
|
||||
PartialShape data_ps{1, 2, 3};
|
||||
|
||||
element::Type axes_et = element::i32;
|
||||
Shape axes_ps{2};
|
||||
std::vector<int64_t> axes{0, 1};
|
||||
|
||||
bool keep_dims = true;
|
||||
|
||||
for (const auto& data_et : element_types)
|
||||
{
|
||||
const ReduceParams params{data_ps, data_et, axes_ps, axes, axes_et, keep_dims};
|
||||
try
|
||||
{
|
||||
auto reduce_op = makeReduceOp<TypeParam>(params);
|
||||
FAIL() << "Invalid element type of data input not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "Element type of data input must be boolean.");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Data input element type validation check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REGISTER_TYPED_TEST_CASE_P(
|
||||
ReduceLogicalTest,
|
||||
reduce_logical_invalid_data_et);
|
@ -2,48 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
TEST(type_prop, reduce_prod_v1_axis_out_of_range)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{2, 3});
|
||||
try
|
||||
{
|
||||
auto reduce_prod = make_shared<op::v1::ReduceProd>(arg, axes);
|
||||
|
||||
// Should have thrown, so fail if it didn't
|
||||
FAIL() << "Incorrect axes values exception not thrown";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Reduction axis ("));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_prod_v1_shape_if_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceProd>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3, 1, 1}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_prod_v1_shape_if_not_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = false;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceProd>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3}));
|
||||
}
|
||||
using Type = ::testing::Types<op::v1::ReduceProd>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_prod, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_prod_et, ReduceArithmeticTest, Type);
|
||||
|
@ -2,48 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
#include "reduce_ops.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
TEST(type_prop, reduce_sum_v1_axis_out_of_range)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{2, 3});
|
||||
try
|
||||
{
|
||||
auto reduce_sum = make_shared<op::v1::ReduceSum>(arg, axes);
|
||||
|
||||
// Should have thrown, so fail if it didn't
|
||||
FAIL() << "Incorrect axes values exception not thrown";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Reduction axis ("));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Deduced type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_sum_v1_shape_if_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = true;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceSum>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3, 1, 1}));
|
||||
}
|
||||
|
||||
TEST(type_prop, reduce_sum_v1_shape_if_not_keep_dims)
|
||||
{
|
||||
auto arg = make_shared<op::Parameter>(element::f32, Shape{3, 4, 5});
|
||||
auto axes = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 2});
|
||||
auto keep_dims = false;
|
||||
auto reduce_prod = make_shared<op::v1::ReduceSum>(arg, axes, keep_dims);
|
||||
ASSERT_TRUE(reduce_prod->get_output_partial_shape(0).compatible(PartialShape{3}));
|
||||
}
|
||||
using Type = ::testing::Types<op::v1::ReduceSum>;
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_sum, ReduceTest, Type);
|
||||
INSTANTIATE_TYPED_TEST_CASE_P(type_prop_reduce_sum_et, ReduceArithmeticTest, Type);
|
||||
|
171
ngraph/test/type_prop/selu.cpp
Normal file
171
ngraph/test/type_prop/selu.cpp
Normal file
@ -0,0 +1,171 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "util/type_prop.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
|
||||
TEST(type_prop, selu_basic_inference_f32_3D)
|
||||
{
|
||||
const auto param = make_shared<op::Parameter>(element::f32, Shape{1, 32, 32});
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto selu = make_shared<op::Selu>(param, alpha, lambda);
|
||||
|
||||
ASSERT_EQ(selu->get_element_type(), element::f32);
|
||||
ASSERT_EQ(selu->get_shape(), (Shape{1, 32, 32}));
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_basic_inference_f16_3D)
|
||||
{
|
||||
const auto param = make_shared<op::Parameter>(element::f16, Shape{1, 32, 32});
|
||||
const auto alpha = make_shared<op::Parameter>(element::f16, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f16, Shape{1});
|
||||
const auto selu = make_shared<op::Selu>(param, alpha, lambda);
|
||||
|
||||
ASSERT_EQ(selu->get_element_type(), element::f16);
|
||||
ASSERT_EQ(selu->get_shape(), (Shape{1, 32, 32}));
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_basic_inference_f32_5D)
|
||||
{
|
||||
const auto param = make_shared<op::Parameter>(element::f32, Shape{12, 135, 221, 31, 15});
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto selu = make_shared<op::Selu>(param, alpha, lambda);
|
||||
|
||||
ASSERT_EQ(selu->get_element_type(), element::f32);
|
||||
ASSERT_EQ(selu->get_shape(), (Shape{12, 135, 221, 31, 15}));
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_basic_inference_f16_5D)
|
||||
{
|
||||
const auto param = make_shared<op::Parameter>(element::f16, Shape{12, 135, 221, 31, 15});
|
||||
const auto alpha = make_shared<op::Parameter>(element::f16, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f16, Shape{1});
|
||||
const auto selu = make_shared<op::Selu>(param, alpha, lambda);
|
||||
|
||||
ASSERT_EQ(selu->get_element_type(), element::f16);
|
||||
ASSERT_EQ(selu->get_shape(), (Shape{12, 135, 221, 31, 15}));
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_incompatible_input_type_boolean)
|
||||
{
|
||||
// Invalid data input element type
|
||||
try
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::boolean, Shape{1, 2, 3, 4});
|
||||
const auto alpha = make_shared<op::Parameter>(element::boolean, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::boolean, Shape{1});
|
||||
auto selu = make_shared<op::Selu>(data, alpha, lambda);
|
||||
// Data input expected to be of numeric type
|
||||
FAIL() << "Invalid input type not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Input element types must be floating-point"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Input type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_incompatible_input_type_i32)
|
||||
{
|
||||
// Invalid data input element type
|
||||
try
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::i32, Shape{1, 2, 3, 4});
|
||||
const auto alpha = make_shared<op::Parameter>(element::i32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::i32, Shape{1});
|
||||
auto selu = make_shared<op::Selu>(data, alpha, lambda);
|
||||
// Data input expected to be of numeric type
|
||||
FAIL() << "Invalid input type not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Input element types must be floating-point"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Input type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_incompatible_input_type_u16)
|
||||
{
|
||||
// Invalid data input element type
|
||||
try
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::u16, Shape{1, 2, 3, 4});
|
||||
const auto alpha = make_shared<op::Parameter>(element::u16, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::u16, Shape{1});
|
||||
auto selu = make_shared<op::Selu>(data, alpha, lambda);
|
||||
// Data input expected to be of numeric type
|
||||
FAIL() << "Invalid input type not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Input element types must be floating-point"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Input type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_incompatible_input_types)
|
||||
{
|
||||
// Invalid data input element type
|
||||
try
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3, 4});
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::u16, Shape{1});
|
||||
auto selu = make_shared<op::Selu>(data, alpha, lambda);
|
||||
// Data input expected to be of numeric type
|
||||
FAIL() << "Inavlid input types not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), std::string("Input element types do not match"));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
FAIL() << "Input type check failed for unexpected reason";
|
||||
}
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_dynamic_rank_input_shape_2D)
|
||||
{
|
||||
const PartialShape param_shape{Dimension::dynamic(), 10};
|
||||
const auto param = std::make_shared<op::Parameter>(element::f32, param_shape);
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{2, 1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto op = std::make_shared<op::Selu>(param, alpha, lambda);
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{Dimension(), 10}));
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_dynamic_rank_input_shape_3D)
|
||||
{
|
||||
const PartialShape param_shape{100, Dimension::dynamic(), 58};
|
||||
const auto param = std::make_shared<op::Parameter>(element::f32, param_shape);
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto op = std::make_shared<op::Selu>(param, alpha, lambda);
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape{100, Dimension(), 58}));
|
||||
}
|
||||
|
||||
TEST(type_prop, selu_dynamic_rank_input_shape_full)
|
||||
{
|
||||
const auto param = std::make_shared<op::Parameter>(element::f32, PartialShape::dynamic());
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto op = std::make_shared<op::Selu>(param, alpha, lambda);
|
||||
ASSERT_TRUE(op->get_output_partial_shape(0).same_scheme(PartialShape::dynamic()));
|
||||
}
|
@ -110,3 +110,104 @@ TEST(type_prop, space_to_batch_dynamic_shape_dynamic_rank)
|
||||
ASSERT_EQ(space_to_batch->get_element_type(), element::f32);
|
||||
ASSERT_EQ(space_to_batch->get_output_partial_shape(0), PartialShape::dynamic());
|
||||
}
|
||||
|
||||
TEST(type_prop, space_to_batch_invalid_element_type_block_shape)
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::f32, Shape{2, 128});
|
||||
auto block_shape = make_shared<op::Constant>(element::f32, Shape{2}, vector<int64_t>{1, 5});
|
||||
auto pads_begin = make_shared<op::Constant>(element::i64, Shape{2}, vector<float>{0, 2});
|
||||
auto pads_end = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{0, 0});
|
||||
|
||||
try
|
||||
{
|
||||
auto space_to_batch =
|
||||
make_shared<op::v1::SpaceToBatch>(data, block_shape, pads_begin, pads_end);
|
||||
// Input element type is float32
|
||||
FAIL() << "Invalid f32 element type for block_shape not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "block_shape must be an integral number");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
FAIL() << "Integral element type node validation check failed for unexpected reason";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(type_prop, space_to_batch_invalid_element_type_pads_begin)
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::f32, Shape{2, 128});
|
||||
auto block_shape = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 5});
|
||||
auto pads_begin = make_shared<op::Constant>(element::f32, Shape{2}, vector<float>{0, 2});
|
||||
auto pads_end = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{0, 0});
|
||||
|
||||
try
|
||||
{
|
||||
auto space_to_batch =
|
||||
make_shared<op::v1::SpaceToBatch>(data, block_shape, pads_begin, pads_end);
|
||||
// Input element type is float32
|
||||
FAIL() << "Invalid f32 element type for pads_begin not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "pads_begin must be an integral number but got");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
FAIL() << "Integral element type node validation check failed for unexpected reason";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(type_prop, space_to_batch_invalid_element_type_pads_end)
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::f32, Shape{2, 128});
|
||||
auto block_shape = make_shared<op::Constant>(element::i16, Shape{2}, vector<int64_t>{1, 5});
|
||||
auto pads_begin = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{0, 2});
|
||||
auto pads_end = make_shared<op::Constant>(element::f32, Shape{2}, vector<float>{0, 0});
|
||||
|
||||
try
|
||||
{
|
||||
auto space_to_batch =
|
||||
make_shared<op::v1::SpaceToBatch>(data, block_shape, pads_begin, pads_end);
|
||||
// Input element type is float32
|
||||
FAIL() << "Invalid f32 element type for pads_end not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "pads_end must be an integral number but got");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
FAIL() << "Integral element type node validation check failed for unexpected reason";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TEST(type_prop, space_to_batch_invalid_value_block_shape)
|
||||
{
|
||||
auto data = make_shared<op::Parameter>(element::f32, Shape{2, 128});
|
||||
auto block_shape = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{-1, -5});
|
||||
auto pads_begin = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{0, 2});
|
||||
auto pads_end = make_shared<op::Constant>(element::i64, Shape{2}, vector<float>{0, 0});
|
||||
|
||||
try
|
||||
{
|
||||
auto space_to_batch =
|
||||
make_shared<op::v1::SpaceToBatch>(data, block_shape, pads_begin, pads_end);
|
||||
// Input element type is float32
|
||||
FAIL() << "Invalid block_shape value not detected";
|
||||
}
|
||||
catch (const NodeValidationFailure& error)
|
||||
{
|
||||
EXPECT_HAS_SUBSTRING(error.what(), "block_shape values must be greater than 0");
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
FAIL() << "block_shape value node validation check failed for unexpected reason";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ TYPED_TEST_CASE_P(ReduceOpsAttrTest);
|
||||
TYPED_TEST_P(ReduceOpsAttrTest, reduce_ops)
|
||||
{
|
||||
Shape in_shape{3, 4, 5};
|
||||
element::Type in_et = element::f32;
|
||||
element::Type in_et = element::dynamic;
|
||||
|
||||
Shape axes_shape{2};
|
||||
element::Type axes_et = element::i64;
|
||||
|
30
ngraph/test/visitors/op/selu.cpp
Normal file
30
ngraph/test/visitors/op/selu.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "ngraph/op/util/attr_types.hpp"
|
||||
#include "ngraph/opsets/opset1.hpp"
|
||||
|
||||
#include "util/visitor.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
using ngraph::test::NodeBuilder;
|
||||
|
||||
TEST(attributes, selu_op)
|
||||
{
|
||||
NodeBuilder::get_ops().register_factory<opset1::Selu>();
|
||||
const auto data_input = make_shared<op::Parameter>(element::f32, Shape{1, 2, 3});
|
||||
const auto alpha = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
const auto lambda = make_shared<op::Parameter>(element::f32, Shape{1});
|
||||
|
||||
const auto op = make_shared<opset1::Selu>(data_input, alpha, lambda);
|
||||
|
||||
NodeBuilder builder(op);
|
||||
const auto expected_attr_count = 0;
|
||||
|
||||
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
|
||||
}
|
33
ngraph/test/visitors/op/space_to_batch.cpp
Normal file
33
ngraph/test/visitors/op/space_to_batch.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "ngraph/ngraph.hpp"
|
||||
#include "ngraph/op/util/attr_types.hpp"
|
||||
#include "ngraph/opsets/opset2.hpp"
|
||||
|
||||
#include "util/visitor.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace ngraph;
|
||||
using ngraph::test::NodeBuilder;
|
||||
|
||||
|
||||
TEST(attributes, space_to_batch_op)
|
||||
{
|
||||
using namespace opset2;
|
||||
|
||||
NodeBuilder::get_ops().register_factory<SpaceToBatch>();
|
||||
auto data = make_shared<op::Parameter>(element::f32, Shape{2, 128});
|
||||
auto block_shape = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{1, 5});
|
||||
auto pads_begin = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{0, 2});
|
||||
auto pads_end = make_shared<op::Constant>(element::i64, Shape{2}, vector<int64_t>{0, 0});
|
||||
auto op = make_shared<SpaceToBatch>(data, block_shape, pads_begin, pads_end);
|
||||
|
||||
NodeBuilder builder(op);
|
||||
const auto expected_attr_count = 0;
|
||||
|
||||
EXPECT_EQ(builder.get_value_map_size(), expected_attr_count);
|
||||
}
|
@ -18,14 +18,72 @@ To run fuzzing you will need [LLVM](https://apt.llvm.org/) components:
|
||||
- lld (linker)
|
||||
- libc++
|
||||
|
||||
## Reproducing Failure Found by Fuzzing
|
||||
|
||||
1. Build `fuzz` test target:
|
||||
## Building fuzz tests
|
||||
|
||||
1. Build openvino
|
||||
|
||||
Build openvino with options `ENABLE_FUZZING` and `ENABLE_SANITIZER` enabled. It
|
||||
is recommended to use clang compiler.
|
||||
|
||||
```bash
|
||||
cmake -DENABLE_TESTS=ON .. && ninja fuzz
|
||||
(\
|
||||
mkdir -p build && cd build && \
|
||||
CC=clang CXX=clang++ cmake .. -DENABLE_FUZZING=ON -DENABLE_SANITIZER=ON -DTREAT_WARNING_AS_ERROR=OFF && \
|
||||
cmake --build . \
|
||||
)
|
||||
```
|
||||
|
||||
2. Run fuzzing test passing a failure reproducer as a command-line argument:
|
||||
2. Build fuzz tests
|
||||
|
||||
Build fuzz tests with options `ENABLE_FUZZING` and `ENABLE_SANITIZER` enabled.
|
||||
You should use the same compiler as was used for the openvino build.
|
||||
|
||||
```bash
|
||||
./read_network-fuzzer crash-reproducer
|
||||
(\
|
||||
mkdir -p tests/fuzz/build && cd tests/fuzz/build && \
|
||||
CC=clang CXX=clang++ cmake .. -DENABLE_FUZZING=ON -DENABLE_SANITIZER=ON -DTREAT_WARNING_AS_ERROR=OFF -DInferenceEngine_DIR=$(pwd)/../../../build && \
|
||||
cmake --build . \
|
||||
)
|
||||
```
|
||||
|
||||
## Running fuzz tests
|
||||
|
||||
1. Prepare fuzzing corpus
|
||||
|
||||
Fuzzing engine needs a set of valid inputs to start fuzzing from. Those files
|
||||
are called a fuzzing corpus. Place valid inputs for the fuzzing test into
|
||||
directory.
|
||||
|
||||
Intel employees can get the corpus as described here
|
||||
https://wiki.ith.intel.com/x/2N42bg.
|
||||
|
||||
2. Run fuzzing
|
||||
|
||||
```bash
|
||||
./read_network-fuzzer -max_total_time=600 ./read_network-corpus
|
||||
```
|
||||
Consider adding those useful command line options:
|
||||
- `-jobs=$(nproc)` runs multiple fuzzing jobs in parallel.
|
||||
- `-rss_limit_mb=0` to ignore out-of-memory issues.
|
||||
|
||||
## Analyzing fuzzing quality
|
||||
|
||||
### Explore code coverage
|
||||
|
||||
To build coverage report after fuzz test execution run:
|
||||
|
||||
```
|
||||
llvm-profdata merge -sparse *.profraw -o default.profdata && \
|
||||
llvm-cov show ./read_network-fuzzer -instr-profile=default.profdata -format=html -output-dir=read_network-coverage
|
||||
```
|
||||
|
||||
## Reproducing findings
|
||||
|
||||
Fuzzing run halts on the first issue identified, prints issue details to stdout and save data to reproduce the issue as a file in the current folder. To debug the issue pass reproducer as command line argument to fuzz test
|
||||
|
||||
```bash
|
||||
./read_network-fuzzer crash-409b5eeed46a8445b7f7b7a2ce5b60a9ad895e3b
|
||||
```
|
||||
|
||||
It is recommended but not required to use binaries built for fuzzing to debug the issues. A binaries built without `ENABLE_FUZZING` options can also be used to reproduce and debug the issues.
|
@ -6,7 +6,7 @@ set(TARGET_NAME fuzz-testhelper)
|
||||
|
||||
file(
|
||||
GLOB SRC_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*-testhelper.cc)
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
|
||||
|
||||
add_library(
|
||||
${TARGET_NAME} STATIC
|
||||
|
40
tests/fuzz/fuzz-testhelper/fuzz-utils.cc
Normal file
40
tests/fuzz/fuzz-testhelper/fuzz-utils.cc
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include "fuzz-utils.h"
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif // _WIN32
|
||||
|
||||
MemoryFile::MemoryFile(const void *data, size_t size) {
|
||||
#ifdef _WIN32
|
||||
throw std::exception("MemoryFile is not implemented for Windows");
|
||||
#else // _WIN32
|
||||
m_name = strdup("/dev/shm/fuzz-XXXXXX");
|
||||
if (!m_name)
|
||||
throw std::bad_alloc();
|
||||
int fd = mkstemp(m_name);
|
||||
if (size) {
|
||||
size_t nbytes = write(fd, data, size);
|
||||
if (nbytes != size) {
|
||||
free(m_name);
|
||||
close(fd);
|
||||
throw std::runtime_error("Failed to write " + std::to_string(size) +
|
||||
" bytes to " + m_name);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
MemoryFile::~MemoryFile() {
|
||||
#ifndef _WIN32
|
||||
unlink(m_name);
|
||||
free(m_name);
|
||||
#endif // _WIN32
|
||||
}
|
19
tests/fuzz/fuzz-testhelper/fuzz-utils.h
Normal file
19
tests/fuzz/fuzz-testhelper/fuzz-utils.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright (C) 2018-2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
class MemoryFile {
|
||||
public:
|
||||
/// Create a memory backed file
|
||||
MemoryFile(const void *data, size_t size);
|
||||
/// Delete memory backed file
|
||||
~MemoryFile();
|
||||
|
||||
/// Get path to a file.
|
||||
const char *name() { return m_name; }
|
||||
|
||||
private:
|
||||
char *m_name;
|
||||
};
|
@ -9,11 +9,14 @@ add_custom_target(fuzz)
|
||||
# Fuzz test target name is source file name without extension.
|
||||
FILE(GLOB tests "*-fuzzer.cc")
|
||||
|
||||
add_subdirectory(../../../thirdparty/cnpy ${CMAKE_CURRENT_BINARY_DIR}/cnpy)
|
||||
add_subdirectory(../../../thirdparty/zlib ${CMAKE_CURRENT_BINARY_DIR}/zlib)
|
||||
|
||||
foreach(test_source ${tests})
|
||||
get_filename_component(test_name ${test_source} NAME_WE)
|
||||
add_fuzzer(${test_name} ${test_source})
|
||||
|
||||
target_link_libraries(${test_name} PRIVATE IE::inference_engine)
|
||||
target_link_libraries(${test_name} PRIVATE IE::inference_engine cnpy zlib)
|
||||
|
||||
add_dependencies(fuzz ${test_name})
|
||||
endforeach()
|
||||
|
21
tests/fuzz/src/cnpy_npy_load-fuzzer.cc
Normal file
21
tests/fuzz/src/cnpy_npy_load-fuzzer.cc
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2021 Intel Corporation
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cnpy.h>
|
||||
#include "fuzz-utils.h"
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t * inputData, size_t inputSize) {
|
||||
MemoryFile file(inputData, inputSize);
|
||||
|
||||
try {
|
||||
cnpy::NpyArray array = cnpy::npy_load(file.name());
|
||||
}
|
||||
catch (const std::exception&) {
|
||||
return 0; // fail gracefully on expected exceptions
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -67,6 +67,7 @@ def metadata_from_manifest(manifest):
|
||||
'commit_sha': repo_trigger['revision'],
|
||||
'commit_date': repo_trigger['commit_time'],
|
||||
'repo_url': repo_trigger['url'],
|
||||
'branch': repo_trigger['branch'],
|
||||
'target_branch': repo_trigger['target_branch'],
|
||||
'event_type': manifest['components'][PRODUCT_NAME]['build_event'].lower(),
|
||||
f'{PRODUCT_NAME}_version': manifest['components'][PRODUCT_NAME]['version'],
|
||||
|
@ -325,10 +325,11 @@ def manifest_metadata(request):
|
||||
"repo_url": {"type": "string"},
|
||||
"commit_sha": {"type": "string"},
|
||||
"commit_date": {"type": "string"},
|
||||
"branch": {"type": "string"},
|
||||
"target_branch": {"type": "string"},
|
||||
"version": {"type": "string"}
|
||||
},
|
||||
"required": ["product_type", "repo_url", "commit_sha", "commit_date", "target_branch", "version"],
|
||||
"required": ["product_type", "repo_url", "commit_sha", "commit_date", "branch", "target_branch", "version"],
|
||||
"additionalProperties": false
|
||||
}
|
||||
"""
|
||||
|
@ -57,7 +57,8 @@ def metadata_from_manifest(manifest: Path):
|
||||
'commit_sha': repo_trigger['revision'],
|
||||
'commit_date': repo_trigger['commit_time'],
|
||||
'repo_url': repo_trigger['url'],
|
||||
'target_branch': repo_trigger['branch'],
|
||||
'branch': repo_trigger['branch'],
|
||||
'target_branch': repo_trigger['target_branch'],
|
||||
'version': manifest['components'][PRODUCT_NAME]['version']
|
||||
}
|
||||
|
||||
|
8
thirdparty/cnpy/cnpy.cpp
vendored
8
thirdparty/cnpy/cnpy.cpp
vendored
@ -90,7 +90,9 @@ void cnpy::parse_npy_header(unsigned char* buffer,size_t& word_size, std::vector
|
||||
//byte order code | stands for not applicable.
|
||||
//not sure when this applies except for byte array
|
||||
loc1 = header.find("descr")+9;
|
||||
bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
bool littleEndian = false;
|
||||
if (loc1 < header.size())
|
||||
littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
assert(littleEndian);
|
||||
|
||||
//char type = header[loc1+1];
|
||||
@ -148,7 +150,9 @@ void cnpy::parse_npy_header(FILE* fp, size_t& word_size, std::vector<size_t>& sh
|
||||
if (loc1 == std::string::npos)
|
||||
throw std::runtime_error("parse_npy_header: failed to find header keyword: 'descr'");
|
||||
loc1 += 9;
|
||||
bool littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
bool littleEndian = false;
|
||||
if (loc1 < header.size())
|
||||
littleEndian = (header[loc1] == '<' || header[loc1] == '|' ? true : false);
|
||||
assert(littleEndian);
|
||||
|
||||
//char type = header[loc1+1];
|
||||
|
5
thirdparty/cnpy/cnpy.h
vendored
5
thirdparty/cnpy/cnpy.h
vendored
@ -27,6 +27,11 @@ namespace cnpy {
|
||||
{
|
||||
num_vals = 1;
|
||||
for(size_t i = 0;i < shape.size();i++) num_vals *= shape[i];
|
||||
if (word_size &&
|
||||
num_vals > std::vector<char>().max_size() / word_size)
|
||||
throw std::length_error("NpyArray of " + std::to_string(num_vals) +
|
||||
"*" + std::to_string(word_size) +
|
||||
" elements is too big.");
|
||||
data_holder = std::shared_ptr<std::vector<char>>(
|
||||
new std::vector<char>(num_vals * word_size));
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ def run(args):
|
||||
set_throughput_streams()
|
||||
|
||||
if MULTI_DEVICE_NAME in device_name and CPU_DEVICE_NAME in device_name:
|
||||
logger.warning("Turn on GPU trottling. Multi-device execution with the CPU + GPU performs best with GPU trottling hint, " +
|
||||
logger.warning("Turn on GPU throttling. Multi-device execution with the CPU + GPU performs best with GPU throttling hint, " +
|
||||
"which releases another CPU thread (that is otherwise used by the GPU driver for active polling)")
|
||||
config[device]['GPU_PLUGIN_THROTTLE'] = '1'
|
||||
elif device == MYRIAD_DEVICE_NAME:
|
||||
|
Loading…
Reference in New Issue
Block a user