2020-02-07 19:01:03 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
# -------------------------------------------------------------------------
|
2020-03-10 19:57:49 +00:00
|
|
|
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
# Licensed under the MIT License. See License.txt in the project root for
|
2020-02-07 19:01:03 +00:00
|
|
|
# license information.
|
|
|
|
|
# --------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
# For live logging, use the command: pytest -o log_cli=true --log-cli-level=DEBUG
|
|
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
import shutil
|
2022-04-26 16:35:16 +00:00
|
|
|
import unittest
|
|
|
|
|
|
2020-06-11 21:19:55 +00:00
|
|
|
import pytest
|
2022-07-21 02:21:26 +00:00
|
|
|
import torch
|
2022-04-26 16:35:16 +00:00
|
|
|
from model_loader import get_fusion_test_model, get_test_data_path
|
2021-08-06 23:16:17 +00:00
|
|
|
from onnx import TensorProto, load_model
|
2021-08-09 17:55:49 +00:00
|
|
|
from parity_utilities import find_transformers_source
|
2022-07-21 02:21:26 +00:00
|
|
|
from transformers import is_tf_available
|
2022-04-26 16:35:16 +00:00
|
|
|
|
2021-08-09 17:55:49 +00:00
|
|
|
if find_transformers_source():
|
2022-07-21 02:21:26 +00:00
|
|
|
from benchmark_helper import ConfigModifier, OptimizerInfo, Precision
|
2022-11-29 21:06:39 +00:00
|
|
|
from fusion_options import FusionOptions
|
2021-08-06 23:16:17 +00:00
|
|
|
from huggingface_models import MODELS
|
2022-04-26 16:35:16 +00:00
|
|
|
from onnx_exporter import export_onnx_model_from_pt, export_onnx_model_from_tf
|
|
|
|
|
from onnx_model import OnnxModel
|
|
|
|
|
from optimizer import optimize_model
|
2021-08-06 23:16:17 +00:00
|
|
|
else:
|
2022-07-21 02:21:26 +00:00
|
|
|
from onnxruntime.transformers.benchmark_helper import ConfigModifier, OptimizerInfo, Precision
|
2022-11-29 21:06:39 +00:00
|
|
|
from onnxruntime.transformers.fusion_options import FusionOptions
|
2021-08-06 23:16:17 +00:00
|
|
|
from onnxruntime.transformers.huggingface_models import MODELS
|
2022-04-26 16:35:16 +00:00
|
|
|
from onnxruntime.transformers.onnx_exporter import export_onnx_model_from_pt, export_onnx_model_from_tf
|
|
|
|
|
from onnxruntime.transformers.onnx_model import OnnxModel
|
|
|
|
|
from onnxruntime.transformers.optimizer import optimize_model
|
2021-08-06 23:16:17 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
TEST_MODELS = {
|
2022-04-26 16:35:16 +00:00
|
|
|
"bert_keras_0": (
|
|
|
|
|
"models",
|
|
|
|
|
"TFBertForSequenceClassification_1.onnx",
|
|
|
|
|
), # bert_mrpc_tensorflow2.1_opset10
|
|
|
|
|
"bert_keras_squad": (
|
|
|
|
|
"models",
|
|
|
|
|
"TFBertForQuestionAnswering.onnx",
|
|
|
|
|
), # bert_squad_tensorflow2.1_keras2onnx_opset11
|
|
|
|
|
"gpt2_past": ("models", "gpt2_past.onnx"), # gpt2_pytorch1.5_opset11
|
|
|
|
|
"gpt2_past_mask": ("FUSION", "gpt2_past_mask_one_layer.onnx"),
|
|
|
|
|
"multiple_embed": ("FUSION", "embed_layer_norm_multiple.onnx"),
|
|
|
|
|
"bert_tf2onnx_0": ("models", "bert_tf2onnx_0.onnx"),
|
2020-02-16 07:59:49 +00:00
|
|
|
}
|
|
|
|
|
|
2020-06-11 21:19:55 +00:00
|
|
|
|
|
|
|
|
def _get_test_model_path(name):
|
2022-07-21 02:21:26 +00:00
|
|
|
sub_dir, file = TEST_MODELS[name]
|
2020-07-10 22:28:27 +00:00
|
|
|
if sub_dir == "FUSION":
|
2021-09-10 07:29:40 +00:00
|
|
|
return get_fusion_test_model(file)
|
2020-07-10 22:28:27 +00:00
|
|
|
else:
|
2021-09-10 07:29:40 +00:00
|
|
|
return get_test_data_path(sub_dir, file)
|
2020-06-11 21:19:55 +00:00
|
|
|
|
2020-03-20 21:34:10 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
class TestModelOptimization(unittest.TestCase):
|
|
|
|
|
def verify_node_count(self, onnx_model, expected_node_count, test_name):
|
2020-02-07 19:01:03 +00:00
|
|
|
for op_type, count in expected_node_count.items():
|
2022-07-21 02:21:26 +00:00
|
|
|
if len(onnx_model.get_nodes_by_op_type(op_type)) != count:
|
2020-05-28 08:16:41 +00:00
|
|
|
print(f"Counters is not expected in test: {test_name}")
|
|
|
|
|
for op, counter in expected_node_count.items():
|
2023-03-24 22:29:03 +00:00
|
|
|
print(f"{op}: {len(onnx_model.get_nodes_by_op_type(op))} expected={counter}")
|
2021-09-03 02:48:07 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
self.assertEqual(len(onnx_model.get_nodes_by_op_type(op_type)), count)
|
2020-02-07 19:01:03 +00:00
|
|
|
|
2022-11-29 21:06:39 +00:00
|
|
|
# test huggingface pytorch model
|
2022-04-26 16:35:16 +00:00
|
|
|
def _test_optimizer_on_huggingface_model(
|
|
|
|
|
self,
|
|
|
|
|
model_name,
|
|
|
|
|
expected_fusion_result_list,
|
|
|
|
|
inputs_count=1,
|
|
|
|
|
validate_model=True,
|
|
|
|
|
):
|
2022-11-29 21:06:39 +00:00
|
|
|
# Remove cached model so that CI machine has enough space. Do not remove cache models in dev machine.
|
|
|
|
|
if not find_transformers_source():
|
|
|
|
|
shutil.rmtree("./cache_models", ignore_errors=True)
|
2022-04-26 16:35:16 +00:00
|
|
|
shutil.rmtree("./onnx_models", ignore_errors=True)
|
2022-11-29 21:06:39 +00:00
|
|
|
|
2020-10-14 02:24:14 +00:00
|
|
|
# expect fusion result list have the following keys
|
|
|
|
|
# EmbedLayerNormalization, Attention, Gelu, FastGelu, BiasGelu, LayerNormalization, SkipLayerNormalization
|
|
|
|
|
model_fusion_statistics = {}
|
|
|
|
|
|
|
|
|
|
input_names = MODELS[model_name][0]
|
|
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
config_modifier = ConfigModifier(None)
|
|
|
|
|
fusion_options = None
|
|
|
|
|
model_class = "AutoModel"
|
2020-10-14 02:24:14 +00:00
|
|
|
with torch.no_grad():
|
2022-04-26 16:35:16 +00:00
|
|
|
_, is_valid_onnx_model, _, _ = export_onnx_model_from_pt(
|
|
|
|
|
model_name,
|
2022-07-21 02:21:26 +00:00
|
|
|
MODELS[model_name][1], # opset version
|
|
|
|
|
MODELS[model_name][2], # use_external_data_format
|
|
|
|
|
MODELS[model_name][3], # optimization model type
|
|
|
|
|
model_class,
|
|
|
|
|
config_modifier,
|
2022-04-26 16:35:16 +00:00
|
|
|
"./cache_models",
|
|
|
|
|
"./onnx_models",
|
|
|
|
|
input_names[:inputs_count],
|
|
|
|
|
False,
|
|
|
|
|
Precision.FLOAT32,
|
|
|
|
|
OptimizerInfo.BYSCRIPT,
|
|
|
|
|
True,
|
|
|
|
|
True,
|
|
|
|
|
True,
|
|
|
|
|
model_fusion_statistics,
|
2022-07-21 02:21:26 +00:00
|
|
|
fusion_options,
|
2022-04-26 16:35:16 +00:00
|
|
|
)
|
2020-10-14 02:24:14 +00:00
|
|
|
|
|
|
|
|
if validate_model:
|
|
|
|
|
self.assertEqual(is_valid_onnx_model, True)
|
2022-11-29 21:06:39 +00:00
|
|
|
|
|
|
|
|
expected_node_count = {
|
|
|
|
|
"EmbedLayerNormalization": expected_fusion_result_list[0],
|
|
|
|
|
"Attention": expected_fusion_result_list[1],
|
|
|
|
|
"Gelu": expected_fusion_result_list[2],
|
|
|
|
|
"FastGelu": expected_fusion_result_list[3],
|
|
|
|
|
"BiasGelu": expected_fusion_result_list[4],
|
|
|
|
|
"LayerNormalization": expected_fusion_result_list[5],
|
|
|
|
|
"SkipLayerNormalization": expected_fusion_result_list[6],
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _onnx_path, value in model_fusion_statistics.items():
|
|
|
|
|
actual_node_count = value
|
|
|
|
|
|
|
|
|
|
for op_type, count in expected_node_count.items():
|
|
|
|
|
if op_type not in actual_node_count or actual_node_count[op_type] != count:
|
|
|
|
|
print(f"expected: {expected_node_count} got {actual_node_count}")
|
|
|
|
|
self.assertTrue(False)
|
2021-01-12 18:38:39 +00:00
|
|
|
|
2020-06-11 21:19:55 +00:00
|
|
|
def test_gpt2_past(self):
|
2022-12-22 07:04:44 +00:00
|
|
|
for enable_skip_layer_norm_fusion in [False, True]:
|
|
|
|
|
input_path = _get_test_model_path("gpt2_past")
|
|
|
|
|
|
|
|
|
|
options = FusionOptions("gpt2")
|
|
|
|
|
options.enable_skip_layer_norm = enable_skip_layer_norm_fusion
|
|
|
|
|
|
|
|
|
|
model = optimize_model(
|
|
|
|
|
input_path,
|
|
|
|
|
"gpt2",
|
|
|
|
|
num_heads=2,
|
|
|
|
|
hidden_size=4,
|
|
|
|
|
optimization_options=options,
|
|
|
|
|
)
|
2020-06-11 21:19:55 +00:00
|
|
|
|
2022-12-22 07:04:44 +00:00
|
|
|
expected_node_count = {
|
|
|
|
|
"EmbedLayerNormalization": 0,
|
|
|
|
|
"Attention": 12,
|
|
|
|
|
"Gelu": 0,
|
|
|
|
|
"FastGelu": 12,
|
|
|
|
|
"BiasGelu": 0,
|
|
|
|
|
# First LayerNorm is never fused to SkipLayerNorm as it doesn't meet the requirements
|
|
|
|
|
"LayerNormalization": 25 if not enable_skip_layer_norm_fusion else 1,
|
|
|
|
|
"SkipLayerNormalization": 0 if not enable_skip_layer_norm_fusion else 24,
|
|
|
|
|
}
|
|
|
|
|
self.verify_node_count(model, expected_node_count, "test_gpt2_past")
|
2020-06-19 21:01:37 +00:00
|
|
|
|
2021-08-06 23:16:17 +00:00
|
|
|
def test_gpt2_past_fp16(self):
|
2022-04-26 16:35:16 +00:00
|
|
|
input_model_path = _get_test_model_path("gpt2_past")
|
2021-08-06 23:16:17 +00:00
|
|
|
model = OnnxModel(load_model(input_model_path, format=None, load_external_data=True))
|
2021-08-27 21:35:38 +00:00
|
|
|
model.convert_float_to_float16(keep_io_types=False, use_symbolic_shape_infer=False)
|
2021-08-06 23:16:17 +00:00
|
|
|
for input in model.graph().input[1:]:
|
|
|
|
|
self.assertEqual(input.type.tensor_type.elem_type, TensorProto.FLOAT16)
|
|
|
|
|
for output in model.graph().output:
|
|
|
|
|
self.assertEqual(output.type.tensor_type.elem_type, TensorProto.FLOAT16)
|
|
|
|
|
|
|
|
|
|
def test_gpt2_past_mask(self):
|
2022-12-22 07:04:44 +00:00
|
|
|
for enable_skip_layer_norm_fusion in [False, True]:
|
|
|
|
|
input_path = _get_test_model_path("gpt2_past_mask")
|
|
|
|
|
|
|
|
|
|
options = FusionOptions("gpt2")
|
|
|
|
|
options.enable_skip_layer_norm = enable_skip_layer_norm_fusion
|
|
|
|
|
|
|
|
|
|
model = optimize_model(
|
|
|
|
|
input_path,
|
|
|
|
|
"gpt2",
|
|
|
|
|
num_heads=2,
|
|
|
|
|
hidden_size=4,
|
|
|
|
|
optimization_options=options,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
expected_node_count = {
|
|
|
|
|
"EmbedLayerNormalization": 1,
|
|
|
|
|
"Attention": 1,
|
|
|
|
|
"Gelu": 0,
|
|
|
|
|
"FastGelu": 1,
|
|
|
|
|
"BiasGelu": 0,
|
|
|
|
|
"LayerNormalization": 1 if not enable_skip_layer_norm_fusion else 0,
|
|
|
|
|
"SkipLayerNormalization": 0 if not enable_skip_layer_norm_fusion else 1,
|
|
|
|
|
}
|
|
|
|
|
self.verify_node_count(model, expected_node_count, "test_gpt2_past_mask")
|
2020-07-10 22:28:27 +00:00
|
|
|
|
|
|
|
|
def test_multiple_embed(self):
|
2022-04-26 16:35:16 +00:00
|
|
|
input_model_path = _get_test_model_path("multiple_embed")
|
|
|
|
|
model = optimize_model(input_model_path, "bert", num_heads=2, hidden_size=4)
|
2020-07-10 22:28:27 +00:00
|
|
|
expected_node_count = {
|
2022-04-26 16:35:16 +00:00
|
|
|
"EmbedLayerNormalization": 2,
|
|
|
|
|
"Attention": 2,
|
|
|
|
|
"Gelu": 0,
|
|
|
|
|
"FastGelu": 0,
|
|
|
|
|
"BiasGelu": 0,
|
|
|
|
|
"LayerNormalization": 0,
|
|
|
|
|
"SkipLayerNormalization": 0,
|
2020-07-10 22:28:27 +00:00
|
|
|
}
|
2022-04-26 16:35:16 +00:00
|
|
|
self.verify_node_count(model, expected_node_count, "test_multiple_embed")
|
2020-07-10 22:28:27 +00:00
|
|
|
|
2021-09-03 02:48:07 +00:00
|
|
|
def test_embed_layer_norm_fusion(self):
|
|
|
|
|
onnx_files = []
|
|
|
|
|
for i in [3, 8, 9]:
|
|
|
|
|
onnx_files.append(f"embed_layer_norm_format{i}.onnx")
|
|
|
|
|
onnx_files.append(f"embed_layer_norm_format{i}_opset13.onnx")
|
2022-04-26 16:35:16 +00:00
|
|
|
onnx_files.append("embed_layer_norm_format3_no_cast.onnx")
|
|
|
|
|
onnx_files.append("embed_layer_norm_format3_no_cast_opset13.onnx")
|
2021-09-03 02:48:07 +00:00
|
|
|
|
2022-11-29 21:06:39 +00:00
|
|
|
options = FusionOptions("bert")
|
|
|
|
|
options.use_raw_attention_mask(False)
|
|
|
|
|
|
2021-09-03 02:48:07 +00:00
|
|
|
for file in onnx_files:
|
2021-09-10 07:29:40 +00:00
|
|
|
input_model_path = get_fusion_test_model(file)
|
2022-11-29 21:06:39 +00:00
|
|
|
model = optimize_model(input_model_path, "bert", optimization_options=options)
|
2022-04-26 16:35:16 +00:00
|
|
|
expected_node_count = {
|
|
|
|
|
"EmbedLayerNormalization": 1,
|
|
|
|
|
"Attention": 1,
|
|
|
|
|
"ReduceSum": 0,
|
|
|
|
|
}
|
2021-09-03 02:48:07 +00:00
|
|
|
self.verify_node_count(model, expected_node_count, file)
|
|
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2021-08-06 23:16:17 +00:00
|
|
|
def test_huggingface_bert_fusion_1(self):
|
2020-12-03 18:52:33 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("bert-base-uncased", [1, 12, 0, 0, 12, 0, 24], inputs_count=1)
|
2021-08-06 23:16:17 +00:00
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_bert_fusion_2(self):
|
2020-12-03 18:52:33 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("bert-base-uncased", [1, 12, 0, 0, 12, 0, 24], inputs_count=2)
|
2021-08-06 23:16:17 +00:00
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_bert_fusion_3(self):
|
2020-12-03 18:52:33 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("bert-base-uncased", [1, 12, 0, 0, 12, 0, 24], inputs_count=3)
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_openaigpt_fusion(self):
|
2023-01-17 18:34:56 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("openai-gpt", [0, 12, 0, 12, 0, 0, 24])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
@unittest.skip("skip failed fusion test of gpt-2 on PyTorch 1.12 and transformers 4.18. TODO: fix it")
|
|
|
|
|
def test_huggingface_gpt2_fusion(self):
|
|
|
|
|
self._test_optimizer_on_huggingface_model("gpt2", [0, 12, 0, 12, 0, 25, 0])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2022-07-21 02:21:26 +00:00
|
|
|
@unittest.skip("skip failed fusion test of xlm on PyTorch 1.12 and transformers 4.18. TODO: fix it")
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_xlm_fusion(self):
|
2020-12-03 18:52:33 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("xlm-mlm-ende-1024", [0, 6, 0, 0, 6, 0, 13])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_roberta_fusion(self):
|
2021-06-09 02:43:59 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("roberta-base", [0, 12, 0, 0, 12, 1, 24])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_distillbert_fusion(self):
|
2020-12-03 18:52:33 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("distilbert-base-uncased", [1, 6, 0, 0, 6, 0, 12], inputs_count=1)
|
|
|
|
|
self._test_optimizer_on_huggingface_model("distilbert-base-uncased", [1, 6, 0, 0, 6, 0, 12], inputs_count=2)
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
@unittest.skip("skip failed fusion test of camembert on PyTorch 1.12 and transformers 4.18. TODO: fix it")
|
|
|
|
|
def test_huggingface_camembert_fusion(self):
|
|
|
|
|
self._test_optimizer_on_huggingface_model("camembert-base", [0, 12, 0, 0, 12, 1, 24], validate_model=False)
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2022-07-21 02:21:26 +00:00
|
|
|
@unittest.skip("skip failed fusion test of albert on PyTorch 1.12 and transformers 4.18. TODO: fix it")
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_albert_fusion(self):
|
2021-06-09 02:43:59 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("albert-base-v1", [0, 12, 0, 0, 12, 1, 24])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
@unittest.skip("skip fusion test of t5 since it is not implemented yet")
|
|
|
|
|
def test_huggingface_t5_fusion(self):
|
|
|
|
|
self._test_optimizer_on_huggingface_model("t5-small", [0, 0, 0, 0, 0, 0, 0])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_xlmroberta_fusion(self):
|
2021-06-09 02:43:59 +00:00
|
|
|
self._test_optimizer_on_huggingface_model("xlm-roberta-base", [0, 12, 0, 0, 12, 1, 24])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2022-07-21 02:21:26 +00:00
|
|
|
@unittest.skip("skip failed fusion test of flaubert on PyTorch 1.12 and transformers 4.18. TODO: fix it")
|
2020-10-14 02:24:14 +00:00
|
|
|
def test_huggingface_flaubert_fusion(self):
|
2022-04-26 16:35:16 +00:00
|
|
|
self._test_optimizer_on_huggingface_model(
|
|
|
|
|
"flaubert/flaubert_base_cased",
|
|
|
|
|
[0, 12, 0, 0, 12, 0, 25],
|
|
|
|
|
validate_model=False,
|
|
|
|
|
)
|
|
|
|
|
self._test_optimizer_on_huggingface_model(
|
|
|
|
|
"flaubert/flaubert_small_cased",
|
|
|
|
|
[0, 6, 0, 0, 6, 12, 1],
|
|
|
|
|
validate_model=False,
|
|
|
|
|
)
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
@unittest.skip("skip failed fusion test of dialogpt on PyTorch 1.12 and transformers 4.18. TODO: fix it")
|
|
|
|
|
def test_huggingface_dialogpt_fusion(self):
|
|
|
|
|
self._test_optimizer_on_huggingface_model("microsoft/DialoGPT-small", [0, 12, 0, 12, 0, 25, 0])
|
2020-10-14 02:24:14 +00:00
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2020-12-15 22:30:15 +00:00
|
|
|
def test_huggingface_bart_fusion(self):
|
|
|
|
|
self._test_optimizer_on_huggingface_model("facebook/bart-base", [0, 0, 0, 0, 12, 2, 30])
|
2021-01-12 18:38:39 +00:00
|
|
|
|
2023-04-04 21:05:24 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_vit_fusion(self):
|
|
|
|
|
self._test_optimizer_on_huggingface_model("google/vit-base-patch16-224", [0, 11, 0, 0, 12, 1, 24])
|
|
|
|
|
|
2022-07-21 02:21:26 +00:00
|
|
|
|
|
|
|
|
@unittest.skipUnless(is_tf_available(), "skip TestBertOptimizationTF since tensorflow is not available")
|
|
|
|
|
class TestTensorflowModelOptimization(unittest.TestCase):
|
2023-03-24 22:29:03 +00:00
|
|
|
def Setup(self): # noqa: N802
|
2022-07-21 02:21:26 +00:00
|
|
|
try:
|
2023-03-24 22:29:03 +00:00
|
|
|
import tf2onnx # noqa: F401
|
2022-07-21 02:21:26 +00:00
|
|
|
except ImportError:
|
|
|
|
|
self.skipTest("skip TestBertOptimizationTF since tf2onnx not installed")
|
|
|
|
|
|
|
|
|
|
def _test_optimizer_on_tf_model(self, model_name, expected_fusion_result_list, inputs_count, validate_model=True):
|
2022-11-29 21:06:39 +00:00
|
|
|
# Remove cached model so that CI machine has enough space. Do not remove cache models in dev machine.
|
|
|
|
|
if not find_transformers_source():
|
|
|
|
|
shutil.rmtree("./cache_models", ignore_errors=True)
|
2022-07-21 02:21:26 +00:00
|
|
|
shutil.rmtree("./onnx_models", ignore_errors=True)
|
|
|
|
|
|
|
|
|
|
# expect fusion result list have the following keys
|
|
|
|
|
# EmbedLayerNormalization, Attention, Gelu, FastGelu, BiasGelu, LayerNormalization, SkipLayerNormalization
|
|
|
|
|
model_fusion_statistics = {}
|
|
|
|
|
print("testing mode ", model_name)
|
|
|
|
|
print("testing input number = ", inputs_count)
|
|
|
|
|
input_names = MODELS[model_name][0]
|
|
|
|
|
|
|
|
|
|
config_modifier = ConfigModifier(None)
|
|
|
|
|
fusion_options = None
|
|
|
|
|
model_class = "AutoModel"
|
|
|
|
|
with torch.no_grad():
|
|
|
|
|
_, is_valid_onnx_model, _, _ = export_onnx_model_from_tf(
|
|
|
|
|
model_name,
|
|
|
|
|
MODELS[model_name][1], # opset version
|
|
|
|
|
MODELS[model_name][2], # use_external_data_format
|
|
|
|
|
MODELS[model_name][3], # optimization model
|
|
|
|
|
model_class,
|
|
|
|
|
config_modifier,
|
|
|
|
|
"./cache_models",
|
|
|
|
|
"./onnx_models",
|
|
|
|
|
input_names[:inputs_count],
|
|
|
|
|
False,
|
|
|
|
|
Precision.FLOAT32,
|
|
|
|
|
True,
|
|
|
|
|
True,
|
|
|
|
|
True,
|
|
|
|
|
True,
|
|
|
|
|
model_fusion_statistics,
|
|
|
|
|
fusion_options,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
onnx_model = list(model_fusion_statistics.keys())[0]
|
|
|
|
|
fusion_result_list = list(model_fusion_statistics[onnx_model].values())
|
|
|
|
|
|
|
|
|
|
if validate_model:
|
|
|
|
|
self.assertEqual(is_valid_onnx_model, True)
|
|
|
|
|
self.assertEqual(fusion_result_list, expected_fusion_result_list)
|
|
|
|
|
|
2021-03-17 03:49:51 +00:00
|
|
|
@pytest.mark.slow
|
2021-08-06 23:16:17 +00:00
|
|
|
def test_huggingface_bert_base_cased_from_tf2onnx_1(self):
|
2021-03-17 22:33:57 +00:00
|
|
|
self._test_optimizer_on_tf_model("bert-base-cased", [0, 12, 0, 0, 0, 0, 25], 1)
|
2021-08-06 23:16:17 +00:00
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_bert_base_cased_from_tf2onnx_2(self):
|
2021-03-17 22:33:57 +00:00
|
|
|
self._test_optimizer_on_tf_model("bert-base-cased", [0, 12, 0, 0, 0, 0, 25], 2)
|
2021-08-06 23:16:17 +00:00
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_bert_base_cased_from_tf2onnx_3(self):
|
2021-03-17 22:33:57 +00:00
|
|
|
self._test_optimizer_on_tf_model("bert-base-cased", [0, 12, 0, 0, 0, 0, 25], 3)
|
2020-03-20 21:34:10 +00:00
|
|
|
|
2021-03-17 22:33:57 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_distilgpt2_from_tf2onnx(self):
|
|
|
|
|
self._test_optimizer_on_tf_model("distilgpt2", [0, 0, 0, 0, 0, 12, 1], 1)
|
|
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_albert_from_tf2onnx(self):
|
|
|
|
|
self._test_optimizer_on_tf_model("albert-base-v1", [0, 0, 0, 0, 0, 0, 25], 1)
|
2021-06-09 02:43:59 +00:00
|
|
|
|
2021-03-17 22:33:57 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_gpt2_from_tf2onnx(self):
|
|
|
|
|
self._test_optimizer_on_tf_model("gpt2", [0, 0, 0, 0, 0, 24, 1], 1, validate_model=False)
|
|
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_roberta_from_tf2onnx(self):
|
|
|
|
|
self._test_optimizer_on_tf_model("roberta-base", [0, 12, 0, 0, 0, 0, 25], 1, validate_model=False)
|
2021-06-09 02:43:59 +00:00
|
|
|
|
2021-03-17 22:33:57 +00:00
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_distilbert_from_tf2onnx(self):
|
|
|
|
|
self._test_optimizer_on_tf_model("distilbert-base-uncased", [0, 0, 0, 0, 0, 0, 13], 1, validate_model=False)
|
|
|
|
|
|
|
|
|
|
@pytest.mark.slow
|
|
|
|
|
def test_huggingface_xlm_from_tf2onnx(self):
|
|
|
|
|
self._test_optimizer_on_tf_model("xlm-mlm-ende-1024", [0, 0, 0, 0, 0, 1, 12], 1, validate_model=False)
|
2021-01-12 18:38:39 +00:00
|
|
|
|
2021-06-09 02:43:59 +00:00
|
|
|
|
2022-04-26 16:35:16 +00:00
|
|
|
if __name__ == "__main__":
|
2021-01-12 18:38:39 +00:00
|
|
|
unittest.main()
|