Skip to content

Commit 6a6730b

Browse files
authored
Add a common benchmark base class and unify the static and dynamic base implementation. (#1249)
* Add a common benchmark base class and unify the static and dynamic base implementation. * Reimplement PaddleAPIBenchmarkBase and PaddleDynamicBenchmarkBase. * Remove redundant import statements. * Skip some tests in CI. * Further polish the base class implementation. * Change the base op benchmark class of tensorflow and pytorch. * Fix the argument list error and enable the compile of program when cinn is enable through environ variables.
1 parent 1566bd1 commit 6a6730b

11 files changed

Lines changed: 784 additions & 754 deletions

api/common/benchmark.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import abc, six
16+
import importlib
17+
18+
19+
@six.add_metaclass(abc.ABCMeta)
20+
class BenchmarkBase(object):
21+
def __init__(self, framework, testing_mode):
22+
self.name = self.__class__.__name__
23+
self.feed_list = None
24+
self.fetch_list = None
25+
self._backward = False
26+
self._framework = framework
27+
self._testing_mode = testing_mode
28+
29+
@property
30+
def backward(self):
31+
return self._backward
32+
33+
def compute_flop_and_byte(self, config):
34+
""" flop is used as a metric for op's performance and it is optional.
35+
"""
36+
return None, None
37+
38+
@abc.abstractmethod
39+
def build_graph(self, config=None):
40+
pass
41+
42+
@abc.abstractmethod
43+
def variable(self, name, shape, dtype, value=None, stop_gradient=False):
44+
pass
45+
46+
@abc.abstractmethod
47+
def layers(self, api_name, module_name=None, **kwargs):
48+
pass
49+
50+
@abc.abstractmethod
51+
def append_gradients(self, targets, inputs):
52+
pass
53+
54+
def get_running_stats(self, use_gpu, config, runtimes, walltimes=None):
55+
try:
56+
module_name = "torch" if self._framework == "pytorch" else self._framework
57+
module = importlib.import_module(module_name)
58+
version = module.__version__
59+
except Exception:
60+
version = "none"
61+
print("Failed to call %s.__version__" % (self._framework))
62+
63+
stats = {
64+
"framework": self._framework,
65+
"version": version,
66+
"name": self.name,
67+
"device": "GPU" if use_gpu else "CPU",
68+
"backward": self._backward,
69+
"total": runtimes
70+
}
71+
72+
if walltimes is not None:
73+
stats["wall_time"] = walltimes
74+
75+
flop, byte = self.compute_flop_and_byte(config)
76+
if flop is not None:
77+
stats["flop"] = flop
78+
if byte is not None:
79+
stats["byte"] = byte
80+
return stats

api/common/feeder.py

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,99 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
from __future__ import print_function
16-
1715
import collections
1816
import numpy as np
1917

20-
from . import paddle_api_benchmark as paddle_api
21-
from . import tensorflow_api_benchmark as tensorflow_api
18+
19+
def _convert_paddle_dtype(dtype, to_string=True):
20+
import paddle
21+
22+
def _trans(to_string, dtype_str, np_dtype):
23+
dtype = dtype_str if to_string else np.dtype(np_dtype)
24+
return dtype
25+
26+
if not isinstance(dtype, paddle.fluid.core.VarDesc.VarType):
27+
raise TypeError("dtype is not of type fluid.core.VarDesc.VarType")
28+
if dtype == paddle.fluid.core.VarDesc.VarType.FP32:
29+
return _trans(to_string, "float32", np.float32)
30+
elif dtype == paddle.fluid.core.VarDesc.VarType.FP64:
31+
return _trans(to_string, "float64", np.float64)
32+
elif dtype == paddle.fluid.core.VarDesc.VarType.FP16:
33+
return _trans(to_string, "float16", np.float16)
34+
elif dtype == paddle.fluid.core.VarDesc.VarType.INT32:
35+
return _trans(to_string, "int32", np.int32)
36+
elif dtype == paddle.fluid.core.VarDesc.VarType.INT16:
37+
return _trans(to_string, "int16", np.int16)
38+
elif dtype == paddle.fluid.core.VarDesc.VarType.INT64:
39+
return _trans(to_string, "int64", np.int64)
40+
elif dtype == paddle.fluid.core.VarDesc.VarType.BOOL:
41+
return _trans(to_string, "bool", np.bool)
42+
elif dtype == paddle.fluid.core.VarDesc.VarType.INT16:
43+
return _trans(to_string, "uint16", np.uint16)
44+
elif dtype == paddle.fluid.core.VarDesc.VarType.UINT8:
45+
return _trans(to_string, "uint8", np.uint8)
46+
elif dtype == paddle.fluid.core.VarDesc.VarType.INT8:
47+
return _trans(to_string, "int8", np.int8)
48+
else:
49+
raise ValueError("Unsupported dtype %s" % dtype)
50+
51+
52+
def _convert_tensorflow_dtype(dtype, to_string=True):
53+
import tensorflow as tf
54+
55+
def _trans(to_string, dtype_str, np_dtype):
56+
dtype = dtype_str if to_string else np.dtype(np_dtype)
57+
return dtype
58+
59+
if dtype == tf.float16:
60+
# tf.float16: 16-bit half-precision floating-point.
61+
return _trans(to_string, "float16", np.float16)
62+
elif dtype == tf.float32:
63+
# tf.float32: 32-bit single-precision floating-point.
64+
return _trans(to_string, "float32", np.float32)
65+
elif dtype == tf.float64:
66+
# tf.float64: 64-bit double-precision floating-point.
67+
return _trans(to_string, "float64", np.float64)
68+
elif dtype == tf.int8:
69+
# tf.int8: 8-bit signed integer.
70+
return _trans(to_string, "int8", np.int8)
71+
elif dtype == tf.uint8:
72+
# tf.uint8: 8-bit unsigned integer.
73+
return _trans(to_string, "uint8", np.uint8)
74+
elif dtype == tf.uint16:
75+
# tf.uint16: 16-bit unsigned integer.
76+
return _trans(to_string, "uint16", np.uint16)
77+
elif dtype == tf.uint32:
78+
# tf.uint32: 32-bit unsigned integer.
79+
return _trans(to_string, "uint32", np.uint32)
80+
elif dtype == tf.uint64:
81+
# tf.uint64: 64-bit unsigned integer.
82+
return _trans(to_string, "uint64", np.uint64)
83+
elif dtype == tf.int16:
84+
# tf.int16: 16-bit signed integer.
85+
return _trans(to_string, "int16", np.int16)
86+
elif dtype == tf.int32:
87+
# tf.int32: 32-bit signed integer.
88+
return _trans(to_string, "int32", np.int32)
89+
elif dtype == tf.int64:
90+
# tf.int64: 64-bit signed integer.
91+
return _trans(to_string, "int64", np.int64)
92+
elif dtype == tf.bool:
93+
# tf.bool: Boolean.
94+
return _trans(to_string, "bool", np.bool)
95+
else:
96+
# tf.bfloat16: 16-bit truncated floating-point.
97+
# tf.complex64: 64-bit single-precision complex.
98+
# tf.complex128: 128-bit double-precision complex.
99+
# tf.string: String.
100+
# tf.qint8: Quantized 8-bit signed integer.
101+
# tf.quint8: Quantized 8-bit unsigned integer.
102+
# tf.qint16: Quantized 16-bit signed integer.
103+
# tf.quint16: Quantized 16-bit unsigned integer.
104+
# tf.qint32: Quantized 32-bit signed integer.
105+
# tf.resource: Handle to a mutable resource.
106+
# tf.variant: Values of arbitrary types.
107+
raise ValueError("Unsupported dtype %s" % dtype)
22108

23109

24110
def copy_feed_spec(feed_spec):
@@ -132,7 +218,7 @@ def to_paddle(self, feed_vars=None):
132218

133219
# Check shape and dtype
134220
var_shape = var.shape
135-
var_dtype = paddle_api.convert_dtype(
221+
var_dtype = _convert_paddle_dtype(
136222
var.dtype, to_string=True)
137223
value = check_shape_and_dtype(var_shape, var_dtype, value)
138224

@@ -173,7 +259,7 @@ def _to_other(self, target_framework, feed_vars=None):
173259
var = feed_list[i]
174260
var_shape = var.shape
175261
if target_framework == "tensorflow":
176-
var_dtype = tensorflow_api.convert_dtype(
262+
var_dtype = _convert_tensorflow_dtype(
177263
var.dtype, to_string=True)
178264
value = check_shape_and_dtype(var_shape, var_dtype, value)
179265

api/common/main.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424

2525
from common import utils
2626
from common import system
27-
from common import api_param
2827
from common import special_op_list
29-
from common import pytorch_api_benchmark
30-
from common import paddle_dynamic_api_benchmark
3128

3229

3330
def _check_gpu_device(use_gpu):
@@ -170,13 +167,13 @@ def _test_with_json_impl(filename, config_id, unknown_dim,
170167
test_main_without_json(pd_obj, tf_obj, pd_dy_obj, torch_obj, config)
171168

172169

173-
def _is_paddle_enabled(args, config):
170+
def is_paddle_enabled(args, config):
174171
if args.task == "accuracy" or args.framework in ["paddle", "both"]:
175172
return True
176173
return False
177174

178175

179-
def _is_tensorflow_enabled(args, config):
176+
def is_tensorflow_enabled(args, config):
180177
if config.run_tf and args.testing_mode == "static":
181178
if args.task == "accuracy" or args.framework in [
182179
"tensorflow", "tf", "both"
@@ -185,7 +182,7 @@ def _is_tensorflow_enabled(args, config):
185182
return False
186183

187184

188-
def _is_torch_enabled(args, config):
185+
def is_torch_enabled(args, config):
189186
if config.run_torch and args.testing_mode == "dynamic":
190187
if args.task == "accuracy" or args.framework in [
191188
"torch", "pytorch", "both"
@@ -231,7 +228,7 @@ def test_main_without_json(pd_obj=None,
231228
use_feed_fetch = True if args.task == "accuracy" else False
232229

233230
feeder_adapter = None
234-
if _is_tensorflow_enabled(args, config):
231+
if is_tensorflow_enabled(args, config):
235232
assert tf_obj is not None, "TensorFlow object is None."
236233
tf_config = config.to_tensorflow()
237234
print(tf_config)
@@ -246,7 +243,7 @@ def test_main_without_json(pd_obj=None,
246243
log_level=args.log_level,
247244
config_params=config.to_string())
248245

249-
if _is_paddle_enabled(args, config) and args.testing_mode == "static":
246+
if is_paddle_enabled(args, config) and args.testing_mode == "static":
250247
assert pd_obj is not None, "Paddle object is None."
251248
print(config)
252249
pd_outputs, pd_stats = pd_obj.run(config, args, use_feed_fetch,
@@ -262,7 +259,7 @@ def test_main_without_json(pd_obj=None,
262259
if pd_outputs == False:
263260
sys.exit(1)
264261

265-
if _is_torch_enabled(args, config):
262+
if is_torch_enabled(args, config):
266263
assert torch_obj is not None, "PyTorch object is None."
267264
import torch
268265
try:
@@ -286,11 +283,11 @@ def test_main_without_json(pd_obj=None,
286283
log_level=args.log_level,
287284
config_params=config.to_string())
288285

289-
if _is_paddle_enabled(args, config) and args.testing_mode == "dynamic":
286+
if is_paddle_enabled(args, config) and args.testing_mode == "dynamic":
290287
assert pd_dy_obj is not None, "Paddle dynamic object is None."
291288
print(config)
292-
pd_dy_outputs, pd_dy_stats = pd_dy_obj.run(config, args,
293-
feeder_adapter)
289+
pd_dy_outputs, pd_dy_stats = pd_dy_obj.run(
290+
config, args, feeder_adapter=feeder_adapter)
294291

295292
if args.task == "speed":
296293
pd_dy_stats["gpu_time"] = args.gpu_time

0 commit comments

Comments
 (0)