permuteStage->output(0)->desc().dimsOrder());
}
- static bool isTrivialPermute(const PermutationIndexVector& permuteDims) {
- for (size_t i = 0; i < permuteDims.size(); ++i)
- if (i != permuteDims[i])
- return false;
+ static bool isTrivialPermute(const PermutationIndexVector& permutation, const vpu::DimValues& dims) {
+ InferenceEngine::SizeVector dimsVector(dims.size());
+ for (const auto& dim : dims) {
+ auto index = dimToIeInd(dim.first, dims.size());
+ dimsVector[dims.size() - 1 - index] = dim.second;
+ }
+ for (size_t i = 0; i < permutation.size() - 1; ++i) {
+ if (i != permutation[i]) {
+ bool swapAdjacentDims = permutation[i] == (i + 1) && permutation[i + 1] == i;
+ bool dimIsOne = dimsVector[i] == 1 || dimsVector[i + 1] == 1;
+ if (swapAdjacentDims && dimIsOne) {
+ i++;
+ } else {
+ return false;
+ }
+ }
+ }
return true;
}
void PassImpl::run(const Model& model) {
VPU_PROFILE(mergePermuteStages);
const StageMergeGroupList stageMergeGroupList = prepareStagesForMerge(model);
-
for (const auto& stageMergeGroup : stageMergeGroupList) {
const auto& firstPermuteStage = stageMergeGroup.first;
auto resultPermutation = permuteVectorFromStageInternal(firstPermuteStage);
if (!outputLayout.empty())
firstPermuteStage->attrs().set(outputOrderKey, outputLayout);
- // if we have no actual permutation, replace it with copy.
- if (isTrivialPermute(resultPermutation)) {
+ // if we have no actual permutation, replace it with copy or reshape.
+ if (isTrivialPermute(resultPermutation, firstPermuteStage->input(0)->desc().dims())) {
auto permuteInput = firstPermuteStage->input(0);
auto permuteOutput = firstPermuteStage->output(0);
if (permuteInput->desc().dimsOrder() == permuteOutput->desc().dimsOrder()) {
auto origLayer = firstPermuteStage->origLayer();
model->removeStage(firstPermuteStage);
- auto copyStage = _stageBuilder->addCopyStage(model, stageName + "@merged-to-copy",
- origLayer, permuteInput, permuteOutput, "Eliminated permute");
- // TODO: make this optional=true with corresponding fixes in eliminate_copy (it expects Special stages now).
- copyStage->attrs().set("optional", false);
+ if (permuteInput->desc().dims() == permuteOutput->desc().dims()) {
+ auto copyStage = _stageBuilder->addCopyStage(model, stageName + "@merged-to-copy",
+ origLayer, permuteInput, permuteOutput, "Eliminated permute");
+ // TODO: make this optional=true with corresponding fixes in eliminate_copy (it expects Special stages now).
+ copyStage->attrs().set("optional", false);
+ } else {
+ _stageBuilder->addReshapeStage(model, stageName + "@merged-to-reshape", origLayer,
+ permuteInput, permuteOutput);
+ }
}
}
}
}
static const std::vector<InferenceEngine::SizeVector> s_inTensors_3D = {
{5, 7, 11},
+ {1, 3, 4},
};
static const std::vector<PermutationsSequence> s_permuteParams_3D = {
+ {{0, 1, 2}, {1, 0, 2}}, // trivial for case with dims {1, 3, 4}
{{1, 2, 0}, {1, 2, 0}},
{{1, 2, 0}, {1, 2, 0}, {1, 2, 0}}, // trivial one.
};
static const std::vector<InferenceEngine::SizeVector> s_inTensors_4D = {
{3, 5, 7, 11},
+ {5, 1, 1, 7},
};
static const std::vector<PermutationsSequence> s_permuteParams_4D = {
+ {{0, 1, 2, 3}, {1, 0, 3, 2}}, //
+ {{0, 1, 2, 3}, {0, 1, 3, 2}}, // trivial for case with dims {5, 1, 1, 7}
{{1, 2, 3, 0}, {1, 2, 3, 0}, {1, 2, 3, 0}},
{{1, 2, 3, 0}, {1, 2, 3, 0}, {1, 2, 3, 0}, {1, 2, 3, 0}}, // trivial one.
};
static const std::vector<InferenceEngine::SizeVector> s_inTensors_5D = {
{2, 3, 5, 7, 11},
+ {2, 3, 1, 7, 11},
};
static const std::vector<PermutationsSequence> s_permuteParams_5D = {
+ {{0, 1, 2, 3, 4}, {0, 1, 3, 2, 4}}, //
+ {{0, 1, 2, 3, 4}, {0, 2, 1, 3, 4}}, // trivial for case with dims {2, 3, 1, 7, 11}
{{0, 4, 1, 2, 3}, {0, 2, 1, 3, 4}},
{{0, 3, 4, 1, 2}, {0, 1, 3, 2, 4}},
{{1, 2, 3, 4, 0}, {1, 2, 3, 4, 0}},