Files
tensorflow--tensorflow/tensorflow/python/ops/split_benchmark.py
T
wehub-resource-sync 8a852e4b4e
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s
chore: import upstream snapshot with attribution
2026-07-13 12:14:16 +08:00

149 lines
5.2 KiB
Python

# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Benchmark for split and grad of split."""
import numpy as np
from tensorflow.core.protobuf import config_pb2
from tensorflow.python.client import session as session_lib
from tensorflow.python.framework import ops
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import control_flow_ops
from tensorflow.python.ops import variables
from tensorflow.python.platform import benchmark
from tensorflow.python.platform import test
from tensorflow.python.platform import tf_logging as logging
def build_graph(device, input_shape, output_sizes, axis):
"""Build a graph containing a sequence of split operations.
Args:
device: string, the device to run on.
input_shape: shape of the input tensor.
output_sizes: size of each output along axis.
axis: axis to be split along.
Returns:
An array of tensors to run()
"""
with ops.device("/%s:0" % device):
# Use a variable to prevent constant folding.
inp = variables.Variable(array_ops.zeros(input_shape, dtype="float32"))
outputs = []
for _ in range(100):
outputs.extend(array_ops.split(inp, output_sizes, axis))
return outputs
class SplitBenchmark(test.Benchmark):
"""Benchmark split!"""
def _run_graph(self, device, output_shape, variable, num_outputs, axis):
"""Run the graph and print its execution time.
Args:
device: string, the device to run on.
output_shape: shape of each output tensors.
variable: whether or not the output shape should be fixed
num_outputs: the number of outputs to split the input into
axis: axis to be split
Returns:
The duration of the run in seconds.
"""
# Fallback to CPU if GPU is requested but not available.
if device == "gpu" and not test.is_gpu_available():
device = "cpu"
graph = ops.Graph()
with graph.as_default():
if not variable:
if axis == 0:
input_shape = [output_shape[0] * num_outputs, output_shape[1]]
sizes = [output_shape[0] for _ in range(num_outputs)]
else:
input_shape = [output_shape[0], output_shape[1] * num_outputs]
sizes = [output_shape[1] for _ in range(num_outputs)]
else:
sizes = np.random.randint(
low=max(1, output_shape[axis] - 2),
high=output_shape[axis] + 2,
size=num_outputs)
total_size = np.sum(sizes)
if axis == 0:
input_shape = [total_size, output_shape[1]]
else:
input_shape = [output_shape[0], total_size]
outputs = build_graph(device, input_shape, sizes, axis)
config = config_pb2.ConfigProto(graph_options=config_pb2.GraphOptions(
optimizer_options=config_pb2.OptimizerOptions(
opt_level=config_pb2.OptimizerOptions.L0)))
with session_lib.Session(graph=graph, config=config) as session:
logging.set_verbosity("info")
variables.global_variables_initializer().run()
bench = benchmark.TensorFlowBenchmark()
bench.run_op_benchmark(
session,
outputs,
mbs=input_shape[0] * input_shape[1] * 4 * 100 / 1e6,
extras={
"input_shape": input_shape,
"variable": variable,
"axis": axis,
},
)
def _get_name(self, device, input_shape, variable, num_outputs, axis):
return "split_%s_%s_%s_%d_%d" % (
device,
str(input_shape).replace(" ", ""),
str(variable),
num_outputs,
axis,
)
def benchmark_split(self):
print("Forward vs backward concat")
shapes = [[2000, 8], [8, 2000], [100, 18], [1000, 18], [10000, 18],
[100, 97], [1000, 97], [10000, 1], [1, 10000]]
axis_ = [1] # 0 is very fast because it doesn't actually do any copying
num_outputs = 100
variable = [False, True] # fixed input size or not
for shape in shapes:
for axis in axis_:
for v in variable:
self._run_graph("gpu", shape, v, num_outputs, axis)
def benchmark_many_splits(self):
"""Benchmark SplitV with large spatial dimensions and many outputs."""
h, w = 1234, 456
# Scenario 1: Many small splits.
# Total channels = 25.
self._run_graph("cpu", [h * w, 1], False, 25, axis=1)
def benchmark_few_large_splits(self):
"""Benchmark SplitV with large spatial dimensions and few large outputs."""
h, w = 1234, 456
# Scenario 2: Few large splits (same total elements)
# Total channels = 25, split into 5 pieces of 5 channels each.
self._run_graph("cpu", [h * w, 5], False, 5, axis=1)
if __name__ == "__main__":
test.main()