xref: /aosp_15_r20/external/tensorflow/tensorflow/lite/experimental/acceleration/mini_benchmark/runner.h (revision b6fb3261f9314811a0f4371741dbb8839866f948)
1 /* Copyright 2021 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 #ifndef TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_MINI_BENCHMARK_RUNNER_H_
16 #define TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_MINI_BENCHMARK_RUNNER_H_
17 
18 #include <string>
19 #include <vector>
20 
21 #include "flatbuffers/flatbuffers.h"  // from @flatbuffers
22 #include "tensorflow/lite/experimental/acceleration/mini_benchmark/status_codes.h"
23 
24 namespace tflite {
25 namespace acceleration {
26 
27 // Class that runs a C-main-function -compatible exported symbol in a separate
28 // process on Android. Support all Android 24+ devices and some 23 devices. May
29 // also work on 22- but has not been tested.
30 //
31 // Requirements on the caller:
32 // - The function to be called must reside in the same shared library as this
33 // code and it must be exported (typically by being extern "C" and having a name
34 // that starts with Java).
35 // - The function to be called must have the same signature as C main:
36 //     extern "C" int Java_foo(int argc, char** argv)
37 // - The librunner_main.so shared object from this directory must
38 // reside in the same location as the shared object above (typically by
39 // depending on the runner_main_library_for_deps target from this
40 // directory in a java_library or java_binary)
41 //
42 // The return values are meant to be detailed enough for telemetry.
43 //
44 // For reasons behind the above restrictions and requirements, see
45 // implementation notes in runner.cc
46 //
47 // Warning: this class will just run the provided code in-process when compiled
48 // for non-Android.
49 class ProcessRunner {
50  public:
51   // Construct ProcessRunner. 'temporary_path' should be a suitable subdirectory
52   // of the app data path for extracting the helper binary on Android P-.
53   //
54   // Since the function will be called through popen() only return values
55   // between 0 and 127 are well-defined.
56   ProcessRunner(const std::string& temporary_path,
57                 const std::string& function_name,
58                 int (*function_pointer)(int argc, char** argv));
59 
60   // Initialize runner.
61   MinibenchmarkStatus Init();
62 
63   // Run function in separate process. Returns function's output to stdout and
64   // the shell exitcode. Stderr is discarded.
65   //
66   // The function will be called with argc and argv corresponding to a command
67   // line like:
68   //     helper_binary function_name (optional: model path) args
69   // If model is not null, runner will use pipe() to pass the model
70   // to subprocess. Otherwise, args[0] should be a model path.
71   // The args are escaped for running through the shell.
72   //
73   // The 'output' and 'exitcode' and `signal` are set as follows based on the
74   // return value:
75   //   kMinibenchmarkUnknownStatus, kMinibenchmarkPreconditionNotMet: undefined
76   //   kMinibenchmarkPopenFailed:
77   //       *output is an empty string
78   //       *exitcode is errno after popen()
79   //       *signal is 0
80   //   kMinibenchmarkCommandFailed, kMinibenchmarkSuccess:
81   //       *output is stdout produced from function
82   //       *exitcode is:
83   //        - if the process terminated normally:
84   //          the return value of the benchmark function or, if function
85   //          loading fails one the MinibenchmarkStatus values listed under
86   //          'Runner main status codes' to describe the failure.
87   //        - if the process has been terminated by a signal: 0
88   //       *signal is:
89   //        - if the process has been terminated by a signal: the signal number
90   //        - 0 otherwise
91   //
92   // To be considered successful, the function must return
93   // kMinibenchmarkSuccess. This is because some GPU drivers call exit(0) as a
94   // bailout and we don't want to confuse that with a successful run.
95   MinibenchmarkStatus Run(flatbuffers::FlatBufferBuilder* model,
96                           const std::vector<std::string>& args,
97                           std::string* output, int* exitcode, int* signal);
98 
99   ProcessRunner(ProcessRunner&) = delete;
100   ProcessRunner& operator=(const ProcessRunner&) = delete;
101 
102  private:
103 #ifndef __ANDROID__
104   int RunInprocess(flatbuffers::FlatBufferBuilder* model,
105                    const std::vector<std::string>& args);
106 #endif  // !__ANDROID__
107   std::string temporary_path_;
108   std::string function_name_;
109   void* function_pointer_;
110   std::string runner_path_;
111   std::string soname_;
112 };
113 
114 }  // namespace acceleration
115 }  // namespace tflite
116 #endif  // TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_MINI_BENCHMARK_RUNNER_H_
117