HiPipe  0.7.0
C++17 data pipeline with Python bindings.
run_graph.hpp
1 /****************************************************************************
2  * hipipe library
3  * Copyright (c) 2017, Cognexa Solutions s.r.o.
4  * Copyright (c) 2018, Iterait a.s.
5  * Author(s) Filip Matzner
6  *
7  * This file is distributed under the MIT License.
8  * See the accompanying file LICENSE.txt for the complete license agreement.
9  ****************************************************************************/
10 
11 #ifndef HIPIPE_TENSORFLOW_RUN_GRAPH_HPP
12 #define HIPIPE_TENSORFLOW_RUN_GRAPH_HPP
13 
14 #include <hipipe/core/utility/tuple.hpp>
15 #include <hipipe/tensorflow/utility/to_tf_type.hpp>
16 
17 #include <tensorflow/core/framework/tensor.h>
18 #include <tensorflow/core/public/session.h>
19 
20 #include <exception>
21 #include <experimental/filesystem>
22 #include <string>
23 #include <vector>
24 
25 namespace hipipe::tensorflow {
26 
41 template <typename... OutTs, typename... InTs>
42 std::tuple<std::tuple<std::vector<OutTs>...>, std::vector<std::vector<long>>>
43 run_graph(::tensorflow::Session& session,
44  const std::vector<std::string>& input_names,
45  const std::tuple<std::vector<InTs>...>& input_data,
46  const std::vector<std::vector<long>>& input_shapes,
47  const std::vector<std::string>& output_names)
48 {
49  assert(ranges::size(input_names) == ranges::size(input_shapes));
50  assert(ranges::size(input_names) == sizeof...(InTs));
51  assert(ranges::size(output_names) == sizeof...(OutTs));
52  std::tuple<InTs...> in_types;
53  std::tuple<OutTs...> out_types;
54 
55  // convert the input data to tensors
56  std::vector<std::pair<std::string, ::tensorflow::Tensor>> feed;
57  utility::tuple_for_each_with_index(input_data, [&](auto& data, auto i) {
58  // build shape
59  ::tensorflow::TensorShape shape;
60  for (long val : input_shapes[i]) shape.AddDim(val);
61  // build data type
62  auto dtype = to_tf_type(std::tuple_element_t<i, decltype(in_types)>{});
63  // allocate tensor
64  ::tensorflow::Tensor tensor{dtype, shape};
65  // copy data into tensor
66  std::copy(data.begin(), data.end(),
67  tensor.flat<std::tuple_element_t<i, decltype(in_types)>>().data());
68  // link the tensor with the corresponding name
69  feed.emplace_back(input_names[i], std::move(tensor));
70  });
71 
72  // run the graph
73  std::vector<::tensorflow::Tensor> outputs;
74  ::tensorflow::Status status = session.Run(feed, output_names, {}, &outputs);
75  if (!status.ok()) {
76  auto msg = std::string{"Failed to run tensorflow graph: "} + status.ToString();
77  throw std::runtime_error(msg);
78  }
79 
80  // convert the result to std::vectors
81  std::tuple<std::vector<OutTs>...> raw_outputs;
82  std::vector<std::vector<long>> output_shapes;
83  utility::tuple_for_each_with_index(raw_outputs, [&](auto& raw_output, auto i) {
84  ::tensorflow::Tensor& output = outputs[i];
85  // allocate space in std::vector
86  raw_output.resize(output.NumElements());
87  // copy the data from tensor to std::vector
88  std::copy_n(output.flat<std::tuple_element_t<i, decltype(out_types)>>().data(),
89  output.NumElements(),
90  raw_output.begin());
91  // convert the shape of the tensor to std::vector
92  std::vector<long> output_shape;
93  for (long d = 0; d < output.dims(); ++d) output_shape.push_back(output.dim_size(d));
94  output_shapes.emplace_back(std::move(output_shape));
95  // for (long s : output.shape()) output_shapes.back().push_back(s);
96  // (std::vector<long>(output.shape().begin(), output.shape().end()));
97  });
98 
99  return {std::move(raw_outputs), std::move(output_shapes)};
100 }
101 
102 } // namespace hipipe::tensorflow
103 #endif
hipipe::tensorflow::run_graph
std::tuple< std::tuple< std::vector< OutTs >... >, std::vector< std::vector< long > > > run_graph(::tensorflow::Session &session, const std::vector< std::string > &input_names, const std::tuple< std::vector< InTs >... > &input_data, const std::vector< std::vector< long >> &input_shapes, const std::vector< std::string > &output_names)
Run a session and feed its graph with the provided inputs.
Definition: run_graph.hpp:49
hipipe::utility::tuple_for_each_with_index
constexpr auto tuple_for_each_with_index(Tuple &&tuple, Fun &&fun)
Similar to tuple_for_each(), but with index available.
Definition: tuple.hpp:421
shape
std::vector< long > shape(const Rng &rng)
Calculates the shape of a multidimensional range.
Definition: ndim.hpp:387
hipipe::stream::copy
auto copy(from_t< FromColumns... > from_cols, to_t< ToColumns... > to_cols)
Copy the data from FromColumns to the respective ToColumns.
Definition: copy.hpp:43