1 /* Copyright 2019 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 
16 #ifndef TENSORFLOW_CORE_GRAPH_BENCHMARK_TESTLIB_H_
17 #define TENSORFLOW_CORE_GRAPH_BENCHMARK_TESTLIB_H_
18 
19 #include "absl/strings/str_cat.h"
20 #include "absl/strings/str_format.h"
21 #include "tensorflow/core/framework/attr_value.pb.h"
22 #include "tensorflow/core/framework/graph.pb.h"
23 #include "tensorflow/core/framework/node_def.pb.h"
24 #include "tensorflow/core/framework/op.h"
25 #include "tensorflow/core/lib/random/philox_random.h"
26 #include "tensorflow/core/lib/random/simple_philox.h"
27 
28 namespace tensorflow {
29 namespace test {
30 
31 REGISTER_OP("Input").Output("y: float");
32 REGISTER_OP("Output")
33     .Input("x: N * float")
34     .Attr("N: int >= 1")
35     .Output("y: float");
36 REGISTER_OP("In2Out1").Input("a: float").Input("b: float").Output("y: float");
37 REGISTER_OP("In4Out1")
38     .Input("a: float")
39     .Input("b: float")
40     .Input("c: float")
41     .Input("d: float")
42     .Output("y: float");
43 REGISTER_OP("In8Out1")
44     .Input("a: float")
45     .Input("b: float")
46     .Input("c: float")
47     .Input("d: float")
48     .Input("e: float")
49     .Input("f: float")
50     .Input("g: float")
51     .Input("h: float")
52     .Output("y: float");
53 REGISTER_OP("In16Out1")
54     .Input("a: float")
55     .Input("b: float")
56     .Input("c: float")
57     .Input("d: float")
58     .Input("e: float")
59     .Input("f: float")
60     .Input("g: float")
61     .Input("h: float")
62     .Input("i: float")
63     .Input("j: float")
64     .Input("k: float")
65     .Input("l: float")
66     .Input("m: float")
67     .Input("n: float")
68     .Input("o: float")
69     .Input("p: float")
70     .Output("y: float");
71 
CreateGraphDef(int num_nodes,int num_edges_per_node)72 GraphDef CreateGraphDef(int num_nodes, int num_edges_per_node) {
73   const int kNumInNodes = 10 * num_edges_per_node;
74   GraphDef graph_def;
75 
76   auto create_node = [](const string& name, const string& op) {
77     NodeDef node;
78     node.set_name(name);
79     node.set_op(op);
80     return node;
81   };
82 
83   NodeDef node;
84   for (int in = 0; in < kNumInNodes; ++in) {
85     node = create_node(/*name=*/absl::StrFormat("in%04d", in), /*op=*/"Input");
86     *graph_def.add_node() = std::move(node);
87   }
88 
89   random::PhiloxRandom philox(301, 17);
90   random::SimplePhilox rnd(&philox);
91   for (int op = 0; op < num_nodes; ++op) {
92     node = create_node(/*name=*/absl::StrFormat("op%05d", op),
93                        /*op=*/absl::StrFormat("In%dOut1", num_edges_per_node));
94     for (int edge = 0; edge < num_edges_per_node; ++edge) {
95       node.add_input(absl::StrFormat("in%04d", rnd.Uniform(kNumInNodes)));
96     }
97     *graph_def.add_node() = std::move(node);
98   }
99 
100   // Add a single sink node. Otherwise a lot of time is spent in
101   // FixupSourceAndSinkEdges().
102   node = create_node(/*name=*/"out", /*op=*/"Output");
103   for (int op = 0; op < num_nodes; ++op) {
104     node.add_input(absl::StrFormat("op%05d", op));
105   }
106   AttrValue attr;
107   attr.set_i(num_nodes);
108   node.mutable_attr()->insert({"N", std::move(attr)});
109   *graph_def.add_node() = std::move(node);
110 
111   return graph_def;
112 }
113 
CreateRandomGraph(int size)114 GraphDef CreateRandomGraph(int size) {
115   random::PhiloxRandom philox(0x12345);
116   random::SimplePhilox rnd(&philox);
117 
118   string prefix = "long_node_name_prefix_to_measure_string_copy_overhead";
119 
120   GraphDef graph;
121   for (int i = 0; i < size; ++i) {
122     const string name = absl::StrCat(prefix, i);
123     const uint32 num_inputs = rnd.Uniform(std::min(i, 5));
124 
125     NodeDef node;
126     node.set_name(name);
127     for (int n = 0; n < num_inputs; ++n) {
128       const uint32 input_node = rnd.Uniform(i);
129       node.add_input(absl::StrCat(prefix, input_node));
130     }
131 
132     *graph.add_node() = std::move(node);
133   }
134 
135   return graph;
136 }
137 
CreateFaninFanoutNodeGraph(int num_fanins,int num_fanouts)138 GraphDef CreateFaninFanoutNodeGraph(int num_fanins, int num_fanouts) {
139   GraphDef graph;
140 
141   auto create_node = [](const string& name) {
142     NodeDef node;
143     node.set_name(name);
144     return node;
145   };
146 
147   NodeDef node = create_node(/*name=*/"node");
148 
149   for (int i = 0; i < num_fanins; ++i) {
150     const string input_node_name = absl::StrFormat("in%05d", i);
151     NodeDef input_node = create_node(/*name=*/input_node_name);
152     *graph.add_node() = std::move(input_node);
153     node.add_input(input_node_name);
154   }
155 
156   for (int i = 0; i < num_fanouts; ++i) {
157     NodeDef output_node = create_node(/*name=*/absl::StrFormat("out%05d", i));
158     output_node.add_input(absl::StrCat(node.name(), ":", i));
159     *graph.add_node() = std::move(output_node);
160   }
161 
162   *graph.add_node() = std::move(node);
163 
164   return graph;
165 }
166 
167 }  // namespace test
168 }  // namespace tensorflow
169 
170 #endif  // TENSORFLOW_CORE_GRAPH_BENCHMARK_TESTLIB_H_
171