1 # Copyright 2017 The TensorFlow 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 """Benchmark for Conv2D op.""" 16 17 from __future__ import absolute_import 18 from __future__ import division 19 from __future__ import print_function 20 21 import itertools 22 import time 23 24 from tensorflow.python.client import session as session_lib 25 from tensorflow.python.framework import dtypes 26 from tensorflow.python.framework import ops 27 from tensorflow.python.ops import control_flow_ops 28 from tensorflow.python.ops import nn_ops 29 from tensorflow.python.ops import random_ops 30 from tensorflow.python.ops import variables 31 from tensorflow.python.platform import test 32 33 34 def build_graph(device, input_shape, filter_shape, strides, padding, dtype, 35 num_iters, warmup_iters): 36 """builds a graph containing a sequence of conv2d operations. 37 38 Args: 39 device: String, the device to run on. 40 input_shape: Shape of the input tensor. 41 filter_shape: Shape of the filter tensor. 42 strides: A list of ints. 1-D of length 4. The stride of sliding 43 window for each dimension of input. 44 padding: A string from: "SAME", "VALID". The type of padding 45 algorithm to use. 46 dtype: Data type for the convolution. 47 num_iters: number of iterations to run conv2d. 48 warmup_iters: number of iterations for warmup runs. 49 50 Returns: 51 An array of tensors to run() 52 """ 53 with ops.device("/%s:0" % device): 54 inp = variables.Variable( 55 random_ops.truncated_normal(input_shape, dtype=dtype)) 56 filt = variables.Variable( 57 random_ops.truncated_normal(filter_shape, dtype=dtype)) 58 59 outputs = [] 60 conv2d_op = nn_ops.conv2d(inp, filt, strides, padding, data_format="NHWC") 61 outputs.append(conv2d_op) 62 for _ in range(1, num_iters): 63 with ops.control_dependencies([conv2d_op]): 64 conv2d_op = nn_ops.conv2d( 65 inp, filt, strides, padding, data_format="NHWC") 66 outputs.append(conv2d_op) 67 68 warmup_groups = [] 69 warmup_conv2d_op = nn_ops.conv2d( 70 inp, filt, strides, padding, data_format="NHWC") 71 warmup_groups.append(warmup_conv2d_op) 72 for _ in range(1, warmup_iters): 73 with ops.control_dependencies([warmup_conv2d_op]): 74 warmup_conv2d_op = nn_ops.conv2d( 75 inp, filt, strides, padding, data_format="NHWC") 76 warmup_groups.append(warmup_conv2d_op) 77 return control_flow_ops.group(*warmup_groups), control_flow_ops.group( 78 *outputs) 79 80 81 class Conv2DBenchmark(test.Benchmark): 82 """Benchmark conv2d!""" 83 84 def _run_graph(self, device, input_shape, filter_shape, strides, padding, 85 dtype, num_iters, warmup_iters): 86 """runs the graph and print its execution time. 87 88 Args: 89 device: String, the device to run on. 90 input_shape: Shape of the input tensor. 91 filter_shape: Shape of the filter tensor. 92 strides: A list of ints. 1-D of length 4. The stride of sliding 93 window for each dimension of input. 94 padding: A string from: "SAME", "VALID". The type of padding 95 algorithm to use. num_iters: Number of iterations to run the 96 benchmark. 97 dtype: Data type for the convolution. 98 num_iters: number of iterations to run conv2d. 99 warmup_iters: number of iterations for warmup runs. 100 101 Returns: 102 The duration of the run in seconds. 103 """ 104 graph = ops.Graph() 105 with graph.as_default(): 106 warmup_outputs, outputs = build_graph(device, input_shape, filter_shape, 107 strides, padding, dtype, num_iters, 108 warmup_iters) 109 with session_lib.Session(graph=graph) as session: 110 variables.global_variables_initializer().run() 111 # warmup runs 112 session.run(warmup_outputs) 113 114 start_time = time.time() 115 session.run(outputs) 116 duration = (time.time() - start_time) / num_iters 117 print("%s %s inputshape:%s filtershape:%s strides:%s padding:%s " 118 "%d iters: %.8f sec" % 119 (device, str(dtype), str(input_shape).replace(" ", ""), 120 str(filter_shape).replace(" ", ""), 121 str(strides).replace(" ", ""), padding, num_iters, duration)) 122 123 name_template = ( 124 "conv2d_{device}_{datatype}_input_shape_{inputshape}_" 125 "filter_shape_{filtershape}_strides_{strides}_padding_{padding}") 126 127 self.report_benchmark( 128 name=name_template.format( 129 device=device, 130 datatype=str(dtype), 131 inputshape=str(input_shape).replace(" ", ""), 132 filtershape=str(filter_shape).replace(" ", ""), 133 strides=str(strides).replace(" ", ""), 134 padding=padding).replace(" ", ""), 135 iters=num_iters, 136 wall_time=duration) 137 138 return duration 139 140 def benchmark_conv2d(self): 141 print("conv2d benchmark:") 142 143 h = 500 144 w = 500 145 fh = 3 146 fw = 3 147 input_shapes = [] 148 filter_shapes = [] 149 data_types = [dtypes.float32, dtypes.float16] 150 for b, c in itertools.product([4, 16, 32], [i for i in range(3, 16)]): 151 input_shapes += [[b, h, w, c]] 152 filter_shapes += [[fh, fw, c, b]] 153 strides = [[1, 2, 2, 1]] 154 paddings = ["VALID", "SAME"] 155 for ishape, fshape in zip(input_shapes, filter_shapes): 156 for dtype in data_types: 157 for stride in strides: 158 for padding in paddings: 159 self._run_graph("gpu", ishape, fshape, stride, padding, dtype, 80, 160 2) 161 162 163 if __name__ == "__main__": 164 test.main() 165