Home | History | Annotate | Download | only in kernels
      1 /* Copyright 2015 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 #include <mutex>
     17 #include <unordered_map>
     18 
     19 #include "tensorflow/core/common_runtime/kernel_benchmark_testlib.h"
     20 #include "tensorflow/core/example/example.pb.h"
     21 #include "tensorflow/core/example/feature.pb.h"
     22 #include "tensorflow/core/framework/op.h"
     23 #include "tensorflow/core/framework/tensor.h"
     24 #include "tensorflow/core/framework/tensor_shape.h"
     25 #include "tensorflow/core/framework/tensor_types.h"
     26 #include "tensorflow/core/framework/types.pb.h"
     27 #include "tensorflow/core/graph/graph.h"
     28 #include "tensorflow/core/graph/node_builder.h"
     29 #include "tensorflow/core/lib/core/status_test_util.h"
     30 #include "tensorflow/core/lib/strings/stringprintf.h"
     31 #include "tensorflow/core/platform/test.h"
     32 #include "tensorflow/core/platform/test_benchmark.h"
     33 #include "tensorflow/core/platform/types.h"
     34 
     35 namespace tensorflow {
     36 
     37 typedef std::map<std::tuple<int, int, int>, Tensor> ExampleTensorMap;
     38 
     39 // Fillers to fill the underlying repeated array in protobuf.
     40 class BytesFiller {
     41  public:
     42   BytesFiller() {}
     43   void operator()(Feature* f, int feature_size) const {
     44     for (int i = 0; i < feature_size; ++i) {
     45       f->mutable_bytes_list()->add_value("abcd1234abcd1234abcd1234abcd1234!");
     46     }
     47   }
     48   Tensor make_dense_default(int feature_size) {
     49     return Tensor(dtype, TensorShape({feature_size}));
     50   }
     51   DataType dtype = DT_STRING;
     52 };
     53 
     54 class Int64Filler {
     55  public:
     56   Int64Filler() {}
     57   void operator()(Feature* f, int feature_size) const {
     58     for (int i = 0; i < feature_size; ++i) {
     59       f->mutable_int64_list()->add_value(1729);
     60     }
     61   }
     62   Tensor make_dense_default(int feature_size) {
     63     return Tensor(dtype, TensorShape({feature_size}));
     64   }
     65   DataType dtype = DT_INT64;
     66 };
     67 
     68 class FloatFiller {
     69  public:
     70   FloatFiller() {}
     71   void operator()(Feature* f, int feature_size) const {
     72     for (int i = 0; i < feature_size; ++i) {
     73       f->mutable_float_list()->add_value(1.729);
     74     }
     75   }
     76   Tensor make_dense_default(int feature_size) {
     77     return Tensor(dtype, TensorShape({feature_size}));
     78   }
     79   DataType dtype = DT_FLOAT;
     80 };
     81 
     82 template <typename T>
     83 struct ExampleStore {
     84  private:
     85   static ExampleTensorMap serialized_example;
     86   static std::once_flag flags_init;
     87 
     88  public:
     89   static ExampleTensorMap& GetSerializedExample() {
     90     std::call_once(flags_init, [] {
     91       AddExample(&serialized_example, 10, 1, 1);
     92       AddExample(&serialized_example, 100, 1, 1);
     93       AddExample(&serialized_example, 1000, 1, 1);
     94       AddExample(&serialized_example, 10, 128, 1);
     95       AddExample(&serialized_example, 100, 128, 1);
     96       AddExample(&serialized_example, 1000, 128, 1);
     97       AddExample(&serialized_example, 10, 512, 1);
     98       AddExample(&serialized_example, 100, 512, 1);
     99       AddExample(&serialized_example, 1000, 512, 1);
    100       AddExample(&serialized_example, 1, 1, 1000000);
    101     });
    102     return serialized_example;
    103   }
    104   typedef T Filler;
    105   static void AddExample(ExampleTensorMap* examples, int num_keys,
    106                          int batch_size, int feature_size) {
    107     Example example;
    108     Filler fill;
    109     Tensor record_string(DT_STRING, TensorShape({batch_size}));
    110     auto string_t = record_string.vec<string>();
    111     example.Clear();
    112     for (int b = 0; b < batch_size; ++b) {
    113       for (int k = 0; k < num_keys; ++k) {
    114         string k_str = strings::Printf("feature_%d", k);
    115         Feature f;
    116         fill(&f, feature_size);
    117         Features* features = example.mutable_features();
    118         (*features->mutable_feature())[k_str] = f;
    119       }
    120       CHECK(example.SerializeToString(&string_t(b)));
    121     }
    122     (*examples)[std::make_tuple(batch_size, num_keys, feature_size)] =
    123         record_string;
    124   }
    125 };
    126 template <typename T>
    127 ExampleTensorMap ExampleStore<T>::serialized_example;
    128 template <typename T>
    129 std::once_flag ExampleStore<T>::flags_init;
    130 
    131 template class ExampleStore<BytesFiller>;
    132 template class ExampleStore<Int64Filler>;
    133 template class ExampleStore<FloatFiller>;
    134 
    135 enum BenchmarkType { kDense, kSparse, kVarLenDense };
    136 
    137 template <typename S, BenchmarkType b_type>
    138 struct BenchmarkOptions {
    139   int benchmark_type = b_type;
    140   typedef S Store;
    141   typename S::Filler filler;
    142 };
    143 
    144 template <typename Options>
    145 static Graph* ParseExample(int batch_size, int num_keys, int feature_size) {
    146   Graph* g = new Graph(OpRegistry::Global());
    147   Tensor& serialized = Options::Store::GetSerializedExample()[std::make_tuple(
    148       batch_size, num_keys, feature_size)];
    149   Tensor names(DT_STRING, TensorShape({batch_size}));
    150 
    151   std::vector<NodeBuilder::NodeOut> sparse_keys;
    152   std::vector<NodeBuilder::NodeOut> dense_keys;
    153   std::vector<NodeBuilder::NodeOut> dense_defaults;
    154   std::vector<DataType> sparse_types;
    155   std::vector<PartialTensorShape> dense_shapes;
    156   Options opt;
    157   for (int i = 0; i < num_keys; ++i) {
    158     Tensor key(DT_STRING, TensorShape());
    159     key.scalar<string>()() = strings::Printf("feature_%d", i);
    160     switch (opt.benchmark_type) {
    161       case kDense:
    162         dense_keys.emplace_back(test::graph::Constant(g, key));
    163         dense_defaults.emplace_back(test::graph::Constant(
    164             g, opt.filler.make_dense_default(feature_size)));
    165         dense_shapes.push_back(PartialTensorShape({feature_size}));
    166         break;
    167       case kVarLenDense:
    168         dense_keys.emplace_back(test::graph::Constant(g, key));
    169         dense_defaults.emplace_back(
    170             test::graph::Constant(g, opt.filler.make_dense_default(1)));
    171         dense_shapes.push_back(PartialTensorShape({-1}));
    172         break;
    173       case kSparse:
    174         sparse_keys.emplace_back(test::graph::Constant(g, key));
    175         sparse_types.push_back(opt.filler.dtype);
    176         break;
    177     }
    178   }
    179 
    180   Node* ret;
    181   TF_EXPECT_OK(NodeBuilder(g->NewName("n"), "ParseExample")
    182                    .Input(test::graph::Constant(g, serialized))
    183                    .Input(test::graph::Constant(g, names))
    184                    .Input(sparse_keys)
    185                    .Input(dense_keys)
    186                    .Input(dense_defaults)
    187                    .Attr("sparse_types", sparse_types)
    188                    .Attr("dense_shapes", dense_shapes)
    189                    .Finalize(g, &ret));
    190 
    191   return g;
    192 }
    193 
    194 template <typename Options>
    195 static Graph* ParseSingleExample(int num_keys, int feature_size) {
    196   Graph* g = new Graph(OpRegistry::Global());
    197   Tensor& serialized_batch_1 =
    198       Options::Store::GetSerializedExample()[std::make_tuple(1, num_keys,
    199                                                              feature_size)];
    200   Tensor serialized(DT_STRING, TensorShape());
    201   serialized.scalar<string>()() = serialized_batch_1.vec<string>()(0);
    202 
    203   std::vector<string> sparse_keys;
    204   std::vector<string> dense_keys;
    205   std::vector<NodeBuilder::NodeOut> dense_defaults;
    206   std::vector<DataType> sparse_types;
    207   std::vector<PartialTensorShape> dense_shapes;
    208   Options opt;
    209   for (int i = 0; i < num_keys; ++i) {
    210     string key = strings::Printf("feature_%d", i);
    211     switch (opt.benchmark_type) {
    212       case kDense:
    213         dense_keys.push_back(key),
    214             dense_defaults.emplace_back(test::graph::Constant(
    215                 g, opt.filler.make_dense_default(feature_size)));
    216         dense_shapes.push_back(PartialTensorShape({feature_size}));
    217         break;
    218       case kVarLenDense:
    219         dense_keys.push_back(key),
    220             dense_defaults.emplace_back(
    221                 test::graph::Constant(g, opt.filler.make_dense_default(1)));
    222         dense_shapes.push_back(PartialTensorShape({-1}));
    223         break;
    224       case kSparse:
    225         sparse_keys.push_back(key), sparse_types.push_back(opt.filler.dtype);
    226         break;
    227     }
    228   }
    229 
    230   Node* ret;
    231   TF_EXPECT_OK(NodeBuilder(g->NewName("n"), "ParseSingleExample")
    232                    .Input(test::graph::Constant(g, serialized))
    233                    .Input(dense_defaults)
    234                    .Attr<int64>("num_sparse", sparse_keys.size())
    235                    .Attr("sparse_keys", sparse_keys)
    236                    .Attr("sparse_types", sparse_types)
    237                    .Attr("dense_keys", dense_keys)
    238                    .Attr("dense_shapes", dense_shapes)
    239                    .Finalize(g, &ret));
    240 
    241   return g;
    242 }
    243 
    244 // Benchmark settings (Sparse, Dense) X (Bytes, Int64, Float)
    245 typedef BenchmarkOptions<ExampleStore<BytesFiller>, kSparse> SparseString;
    246 typedef BenchmarkOptions<ExampleStore<BytesFiller>, kDense> DenseString;
    247 typedef BenchmarkOptions<ExampleStore<BytesFiller>, kVarLenDense>
    248     VarLenDenseString;
    249 typedef BenchmarkOptions<ExampleStore<Int64Filler>, kSparse> SparseInt64;
    250 typedef BenchmarkOptions<ExampleStore<Int64Filler>, kDense> DenseInt64;
    251 typedef BenchmarkOptions<ExampleStore<Int64Filler>, kVarLenDense>
    252     VarLenDenseInt64;
    253 typedef BenchmarkOptions<ExampleStore<FloatFiller>, kSparse> SparseFloat;
    254 typedef BenchmarkOptions<ExampleStore<FloatFiller>, kDense> DenseFloat;
    255 typedef BenchmarkOptions<ExampleStore<FloatFiller>, kVarLenDense>
    256     VarLenDenseFloat;
    257 
    258 // B == batch_size, K == num_keys. F == feature_size.
    259 // K must be one of 10, 100, 1000
    260 #define BM_ParseExample(TYPE, B, K, F)                                   \
    261   static void BM_ParseExample##_##TYPE##_##B##_##K##_##F(int iters) {    \
    262     int64 items_per_iter = static_cast<int64>(B) * K * F;                \
    263     testing::UseRealTime();                                              \
    264     testing::ItemsProcessed(static_cast<int64>(iters) * items_per_iter); \
    265     test::Benchmark("cpu", ParseExample<TYPE>(B, K, F)).Run(iters);      \
    266   }                                                                      \
    267   BENCHMARK(BM_ParseExample##_##TYPE##_##B##_##K##_##F);
    268 
    269 #define BM_AllParseExample(Type)       \
    270   BM_ParseExample(Type, 1, 10, 1);     \
    271   BM_ParseExample(Type, 128, 10, 1);   \
    272   BM_ParseExample(Type, 512, 10, 1);   \
    273   BM_ParseExample(Type, 1, 100, 1);    \
    274   BM_ParseExample(Type, 128, 100, 1);  \
    275   BM_ParseExample(Type, 512, 100, 1);  \
    276   BM_ParseExample(Type, 1, 1000, 1);   \
    277   BM_ParseExample(Type, 128, 1000, 1); \
    278   BM_ParseExample(Type, 512, 1000, 1); \
    279   BM_ParseExample(Type, 1, 1, 1000000);
    280 
    281 BM_AllParseExample(SparseString);
    282 BM_AllParseExample(DenseString);
    283 BM_AllParseExample(VarLenDenseString);
    284 BM_AllParseExample(SparseInt64);
    285 BM_AllParseExample(DenseInt64);
    286 BM_AllParseExample(VarLenDenseInt64);
    287 BM_AllParseExample(SparseFloat);
    288 BM_AllParseExample(DenseFloat);
    289 BM_AllParseExample(VarLenDenseFloat);
    290 
    291 // K == num_keys. F == feature_size.
    292 // K must be one of 10, 100, 1000
    293 #define BM_ParseSingleExample(TYPE, K, F)                                \
    294   static void BM_ParseSingleExample##_##TYPE##_1_##K##_##F(int iters) {  \
    295     int64 items_per_iter = K * F;                                        \
    296     testing::UseRealTime();                                              \
    297     testing::ItemsProcessed(static_cast<int64>(iters) * items_per_iter); \
    298     test::Benchmark("cpu", ParseSingleExample<TYPE>(K, F)).Run(iters);   \
    299   }                                                                      \
    300   BENCHMARK(BM_ParseSingleExample##_##TYPE##_1_##K##_##F);
    301 
    302 #define BM_AllParseSingleExample(Type)  \
    303   BM_ParseSingleExample(Type, 10, 1);   \
    304   BM_ParseSingleExample(Type, 100, 1);  \
    305   BM_ParseSingleExample(Type, 1000, 1); \
    306   BM_ParseSingleExample(Type, 1, 1000000);
    307 
    308 BM_AllParseSingleExample(SparseString);
    309 BM_AllParseSingleExample(DenseString);
    310 BM_AllParseSingleExample(VarLenDenseString);
    311 BM_AllParseSingleExample(SparseInt64);
    312 BM_AllParseSingleExample(DenseInt64);
    313 BM_AllParseSingleExample(VarLenDenseInt64);
    314 BM_AllParseSingleExample(SparseFloat);
    315 BM_AllParseSingleExample(DenseFloat);
    316 BM_AllParseSingleExample(VarLenDenseFloat);
    317 
    318 }  // end namespace tensorflow
    319