Open11

CREStereo の OAK-D 最適化検証

PINTOPINTO
  • MVN の Myriad コンパイルエラーを回避するため、ONNX から OpenVINO へ変換する過程で MVN が生成されないようにONNXを改造する必要がある。
  • まずは、CREStereoMVN 変換が実行される箇所のみを切り出す
  • 自作ONNX分離ツール sne4onnx を使用
CREStereoの部分グラフ抽出
sne4onnx \
--input_onnx_file_path crestereo_init_iter2_120x160.onnx \
--input_op_names onnx::MatMul_1030 \
--output_op_names onnx::Mul_1041 \
--output_onnx_file_path crestereo_init_iter2_120x160_mvn.onnx

PINTOPINTO
  • 元のモデルの Einsum の部分でONNXがシェイプ推定できていなくて MatMul の入力が unk__105 になってしまっている
  • ONNX から OpenVINO へ変換する前に unk__105 の部分を静的形状に変更する
  • とりあえず、部分グラフを抽出する前にモデル全体を OpenVINO で変換したときの MVN の入力形状は形状推定に成功しているので、その入力形状を参考に固定値に書き換える。この場合は [1, 70, 256]。OpenVINO超優秀。
  • OpenVINOへ変換したあとの CREStereo の MVN の箇所
PINTOPINTO
  • いったん、抽出した部分グラフが OpenVINO -> Myriad でどのように変換されるかを見てみる
ONNX -> OpenVINO
$INTEL_OPENVINO_DIR/deployment_tools/model_optimizer/mo.py \
--input_model crestereo_init_iter2_120x160_mvn.onnx \
--data_type FP16 \
--output_dir crestereo_init_iter2_120x160_mvn/openvino/FP16 \
--model_name crestereo_init_iter2_120x160_mvn
  • 成功。ただし、本当は MVN が生成されてほしくない。Myriad コンパイラがエラーになるので。
mkdir -p crestereo_init_iter2_120x160_mvn/openvino/myriad
${INTEL_OPENVINO_DIR}/deployment_tools/inference_engine/lib/intel64/myriad_compile \
-m crestereo_init_iter2_120x160_mvn/openvino/FP16/crestereo_init_iter2_120x160_mvn.xml \
-ip U8 \
-VPU_NUMBER_OF_SHAVES 4 \
-VPU_NUMBER_OF_CMX_SLICES 4 \
-o crestereo_init_iter2_120x160_mvn/openvino/myriad/crestereo_init_iter2_120x160_mvn.blob
  • 想定通り Myriad Compile でエラー。
Inference Engine: 
	IE version ......... 2021.4.0
	Build ........... 2021.4.0-3839-cd81789d294-releases/2021/4
[Warning][VPU][Config] Deprecated option was used : VPU_MYRIAD_PLATFORM
[ GENERAL_ERROR ] 
/home/jenkins/agent/workspace/private-ci/ie/build-linux-ubuntu20/b/repos/openvino/inference-engine/src/vpu/graph_transformer/src/frontend/frontend.cpp:439 Failed to compile layer "onnx::Mul_1041": [ GENERAL_ERROR ] 
/home/jenkins/agent/workspace/private-ci/ie/build-linux-ubuntu20/b/repos/openvino/inference-engine/src/vpu/graph_transformer/src/stages/mvn.cpp:92 Unsupported combination of indices in layer "onnx::Mul_1041". Only across channel and full batch supported.
PINTOPINTO
  • ONNXの部分グラフに Multiply を外挿する
avoid_mvn.py
import onnx
import onnx_graphsurgeon as gs
import numpy as np

# Load
onnx_graph = onnx.load('crestereo_init_iter2_120x160_mvn.onnx')
graph = gs.import_onnx(onnx_graph)

# Finding outputs for connection
mod_output = None
for graph_node in graph.nodes:
    if graph_node.name == 'Sub_650':
        for node_output in graph_node.outputs:
            if node_output.name == 'onnx::Pow_1034':
                mod_output = node_output
                break

# Generate dummy Multiply OP
# https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Mul-7
# https://docs.openvino.ai/latest/openvino_docs_ops_arithmetic_Multiply_1.html
mul_node = gs.Node(
    op="Mul",
    name=f"{mod_output.name}_dummy_mul",
    inputs=[
        mod_output,
        gs.Constant(
            name=f"{mod_output.name}_dummy_mul_input",
            values=np.asarray([1.0], dtype=np.float32)
        ),
    ],
    outputs=[
        gs.Variable(
            name=f"{mod_output.name}_dummy_mul_output",
            dtype=np.float32, shape=[1,70,256]
        ),
    ]
)
graph.nodes.append(mul_node)

# Finding inputs for connection
mod_input = None
for node_idx, graph_node in enumerate(graph.nodes):
    if graph_node.name == 'Div_657':
        for input_idx, node_input in enumerate(graph_node.inputs):
            if node_input.name == 'onnx::Pow_1034':
                graph.nodes[node_idx].inputs[input_idx] = mul_node.outputs[0]
                break

# Cleanup
graph.cleanup().toposort()
# Export
changed_graph = gs.export_onnx(graph)
# Shape inference
new_model = onnx.shape_inference.infer_shapes(changed_graph)
# Save
onnx.save(new_model, 'crestereo_init_iter2_120x160_mvn_mul.onnx')

PINTOPINTO
  • OpenVINO がちゃんと混乱するかどうかを検証。
$INTEL_OPENVINO_DIR/deployment_tools/model_optimizer/mo.py \
--input_model crestereo_init_iter2_120x160_mvn_mul.onnx \
--data_type FP16 \
--output_dir crestereo_init_iter2_120x160_mvn_mul/openvino/FP16 \
--model_name crestereo_init_iter2_120x160_mvn_mul
  • OpenVINO Model Optimizer を騙すことに成功

  • ただ、まだ Power が残っているので Myriad Compile は失敗する想定

mkdir -p crestereo_init_iter2_120x160_mvn_mul/openvino/myriad
${INTEL_OPENVINO_DIR}/deployment_tools/inference_engine/lib/intel64/myriad_compile \
-m crestereo_init_iter2_120x160_mvn_mul/openvino/FP16/crestereo_init_iter2_120x160_mvn_mul.xml \
-ip U8 \
-VPU_NUMBER_OF_SHAVES 4 \
-VPU_NUMBER_OF_CMX_SLICES 4 \
-o crestereo_init_iter2_120x160_mvn_mul/openvino/myriad/crestereo_init_iter2_120x160_mvn_mul.blob
  • と、思ったら Myriad Blob の生成に成功してしまった。。。
Inference Engine: 
	IE version ......... 2021.4.0
	Build ........... 2021.4.0-3839-cd81789d294-releases/2021/4
[Warning][VPU][Config] Deprecated option was used : VPU_MYRIAD_PLATFORM
Done
PINTOPINTO
onnx -> OpenVINO
$INTEL_OPENVINO_DIR/deployment_tools/model_optimizer/mo.py \
--input_model crestereo_init_iter2_120x160_avoid_mvn.onnx \
--data_type FP16 \
--output_dir crestereo_init_iter2_120x160_avoid_mvn/openvino/FP16 \
--model_name crestereo_init_iter2_120x160_avoid_mvn
OpenVINO -> Myriad
mkdir -p crestereo_init_iter2_120x160_avoid_mvn/openvino/myriad
${INTEL_OPENVINO_DIR}/deployment_tools/inference_engine/lib/intel64/myriad_compile \
-m crestereo_init_iter2_120x160_avoid_mvn/openvino/FP16/crestereo_init_iter2_120x160_avoid_mvn.xml \
-ip U8 \
-VPU_NUMBER_OF_SHAVES 4 \
-VPU_NUMBER_OF_CMX_SLICES 4 \
-o crestereo_init_iter2_120x160_avoid_mvn/openvino/myriad/crestereo_init_iter2_120x160_avoid_mvn.blob
PINTOPINTO
  • 新しいエラー。Less OPは INT64, INT32 の入力を受け付けないので Float16, Float32 にせよ。
Inference Engine: 
	IE version ......... 2021.4.0
	Build ........... 2021.4.0-3839-cd81789d294-releases/2021/4
[Warning][VPU][Config] Deprecated option was used : VPU_MYRIAD_PLATFORM
Less_1562 of type Less: [ GENERAL_ERROR ] 
/home/jenkins/agent/workspace/private-ci/ie/build-linux-ubuntu20/b/repos/openvino/inference-engine/src/vpu/graph_transformer/src/stages/eltwise.cpp:160 Stage node Less_1562 (Less) types check error: input #0 has type S32, but one of [FP16] is expected

PINTOPINTO
  • 元のONNXグラフ全体に対して問題が発生する全ての MVN の生成を阻害するための Mul を挿入する。なお、全ての MVN が対象ではない点に注意。
  • LessGreater の型変換エラーに対処するため、前後に Cast を挟んで INT64Float32 を相互に変換する
  • Expand の型変換エラーに対処するため、前後に Cast を挟んで INT64Float32 を相互に変換する