rs-benchmark.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
3 
4 #include <librealsense2/rs.hpp>
5 #include <glad/glad.h>
6 #include <GLFW/glfw3.h>
8 
9 #include <iostream>
10 #include <iomanip>
11 #include <map>
12 #include <set>
13 #include <cstring>
14 #include <chrono>
15 #include <numeric>
16 #include <math.h>
17 #include <fstream>
18 
19 #include "tclap/CmdLine.h"
20 
21 using namespace std;
22 using namespace chrono;
23 using namespace TCLAP;
24 using namespace rs2;
25 
26 #if (defined(_WIN32) || defined(_WIN64))
27 #include <intrin.h>
28 
29 string get_cpu()
30 {
31  // Based on: https://weseetips.wordpress.com/tag/c-get-cpu-name/
32  // Get extended ids.
33  int CPUInfo[4] = { -1 };
34  __cpuid(CPUInfo, 0x80000000);
35  unsigned int nExIds = CPUInfo[0];
36 
37  // Get the information associated with each extended ID.
38  char CPUBrandString[0x40] = { 0 };
39  for (unsigned int i = 0x80000000; i <= nExIds; ++i)
40  {
41  __cpuid(CPUInfo, i);
42 
43  // Interpret CPU brand string and cache information.
44  if (i == 0x80000002)
45  {
46  memcpy(CPUBrandString,
47  CPUInfo,
48  sizeof(CPUInfo));
49  }
50  else if (i == 0x80000003)
51  {
52  memcpy(CPUBrandString + 16,
53  CPUInfo,
54  sizeof(CPUInfo));
55  }
56  else if (i == 0x80000004)
57  {
58  memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
59  }
60  }
61 
62  char* ptr = CPUBrandString;
63  while (*ptr == ' ') ptr++;
64  return ptr;
65 }
66 
67 #elif defined __linux__ || defined(__linux__)
68 string get_cpu() {
69  // Based on: http://forums.codeguru.com/showthread.php?472578-How-to-get-the-cpu-information-on-linux
70  string line;
71  ifstream finfo("/proc/cpuinfo");
72  while(getline(finfo,line))
73  {
74  stringstream str(line);
75  string itype;
76  string info;
77  if (getline(str, itype, ':') && getline(str, info) && itype.substr(0, 10) == "model name")
78  {
79  return info;
80  }
81  }
82  return "unknown";
83 }
84 #elif __APPLE__
85 string get_cpu() { return "unknown"; }
86 #else
87 string get_cpu() { return "unknown"; }
88 #endif
89 
90 class test
91 {
92 public:
93  virtual frame prepare(frame f) { return f; };
94  virtual frame process(frame f) = 0;
95  virtual frame finish (frame f) { return f; };
96  virtual const std::string& name() const = 0;
97 };
98 
99 template<class T>
100 class pb_test : public test
101 {
102 public:
104  : _block(), _name(std::move(name)) {}
105 
106  frame process(frame f) override
107  {
108  return _block.process(f);
109  }
110  virtual const std::string& name() const override
111  {
112  return _name;
113  }
114 private:
117 };
118 
119 template<class T>
120 class gl_test : public pb_test<T>
121 {
122 public:
124  : pb_test<T>(std::move(name)) {}
125 
126 
127  void flush()
128  {
129  glFlush();
130  glFinish();
131  }
132 
133  frame process(frame f) override
134  {
135  auto res = pb_test<T>::process(f);
136  flush();
137  return res;
138  }
139  frame prepare(frame f) override
140  {
141  auto res = _upload.process(f);
142  flush();
143  return res;
144  }
145  frame finish(frame f) override
146  {
147  _ptr = (void*)f.get_data();
148  return f;
149  }
150 private:
152  volatile void* _ptr;
153 };
154 
155 class suite
156 {
157 public:
158  virtual void register_tests(stream_profile stream,
159  vector<shared_ptr<test>>& tests) const = 0;
160 };
161 
162 #define REGISTER_TEST(x) tests.push_back(make_shared<pb_test<x>>(#x))
163 
164 class processing_blocks : public suite
165 {
166 public:
168  vector<shared_ptr<test>>& tests) const override
169  {
170  if (stream.stream_type() == RS2_STREAM_DEPTH)
171  {
179  }
180  if (stream.format() == RS2_FORMAT_YUYV)
181  {
183  }
184  }
185 };
186 
187 #define REGISTER_GL_TEST(x) tests.push_back(make_shared<gl_test<x>>(#x))
188 
189 class gl_blocks : public suite
190 {
191 public:
193  vector<shared_ptr<test>>& tests) const override
194  {
195  if (stream.stream_type() == RS2_STREAM_DEPTH)
196  {
199  }
200  if (stream.format() == RS2_FORMAT_YUYV)
201  {
203  }
204  }
205 };
206 
207 int main(int argc, char** argv) try
208 {
209  CmdLine cmd("librealsense rs-benchmark tool", ' ', RS2_API_VERSION_STR);
210  cmd.parse(argc, argv);
211 
212  glfwInit();
214  auto win = glfwCreateWindow(100,100,"offscreen",0,0);
217 
218  auto renderer = (const char*)glGetString(GL_RENDERER);
219  auto version = (const char*)glGetString(GL_VERSION);
220 
221  cout << endl;
222  cout << "| | |" << endl;
223  cout << "|------------|-----|" << endl;
224 
225  cout << "|**CPU** |" << get_cpu() << " |" << endl;
226  cout << "|**GPU** | " << renderer << " |" << endl;
227  cout << "|**Graphics Driver** |" << version << " |" << endl;
228 
229  vector<shared_ptr<suite>> suites;
230  suites.push_back(make_shared<processing_blocks>());
231 
232 #ifndef __APPLE__
233  gl::init_processing(win, true);
234  suites.push_back(make_shared<gl_blocks>());
235 #endif
236 
237  pipeline p;
238  config cfg;
241  auto prof = p.start(cfg);
242  auto dev = prof.get_device();
243  auto name = dev.get_info(RS2_CAMERA_INFO_NAME);
244  cout << "|**Device Name** |" << name << " |" << endl << endl;
245  cout.precision(3);
246 
247  for (auto stream : prof.get_streams())
248  {
249  cout << "**Stream Type**: " << stream.stream_name();
250  if (auto vs = stream.as<video_stream_profile>())
251  {
252  cout << ", **Resolution**: " << vs.width() << " x " << vs.height() << endl;
253  }
254  auto fps = stream.fps();
255 
256  vector<shared_ptr<test>> procs;
257  for (auto&& suite : suites)
258  suite->register_tests(stream, procs);
259 
260  vector<frame> frames;
261  for (int i = 0; i < 5 * fps; i++)
262  {
263  auto fs = p.wait_for_frames();
264  for (auto&& f : fs)
265  if (f.get_profile().unique_id() == stream.unique_id())
266  {
267  f.keep();
268  frames.push_back(f);
269  }
270  }
271 
272  cout << endl;
273  cout << "|Filter Name |Step |Median(m) |Mean(m) |STD(m) |Max(m) | Max FPS |" << endl;
274  cout << "|------------|-----|------------|---------|--------|--------|---------|" << endl;
275 
276  string last_name = "";
277  for (auto&& test : procs)
278  {
279  map<string, vector<double>> steps;
280 
281  for (auto&& f : frames)
282  {
284  auto f1 = test->prepare(f);
286  auto f2 = test->process(f1);
287  auto p3 = high_resolution_clock::now();
288  test->finish(f2);
289  auto p4 = high_resolution_clock::now();
290 
291  auto prep = duration_cast<microseconds>(p2 - p1).count();
292  auto proc = duration_cast<microseconds>(p3 - p2).count();
293  auto down = duration_cast<microseconds>(p4 - p3).count();
294  auto total = duration_cast<microseconds>(p4 - p1).count();
295 
296  steps[" Upload"].push_back(prep * 0.001);
297  steps["Calculate"].push_back(proc * 0.001);
298  steps["Download"].push_back(down * 0.001);
299  steps["Total"].push_back(total * 0.001);
300  }
301 
302  int printed_steps = 0;
303  for (auto&& sm : steps)
304  {
305  if (sm.first == "Total" && printed_steps < 2) continue;
306 
307  auto& m = sm.second;
308  double max = *max_element(m.begin(), m.end());
309  double sum = accumulate(m.begin(), m.end(), 0.0);
310  double mean = sum / m.size();
311  double sq_sum = inner_product(m.begin(), m.end(), m.begin(), 0.0);
312  double stdev = sqrt(sq_sum / m.size() - mean * mean);
313  sort(m.begin(), m.end());
314  double median = m[m.size() / 2];
315 
316  vector<int> fps_values{ 6, 15, 30, 60, 90 };
317 
318  auto expected_max = mean + 1.645 * stdev; // 95-percentile - camera spec allows up to 5% outliers
319 
320  int best_fps = 1;
321  for (int fps : fps_values)
322  {
323  auto max_allowed = 1000.0 / fps;
324  if (expected_max < max_allowed) best_fps = fps;
325  }
326 
327  if (sm.first == "Calculate" || median > 0.001)
328  {
329  bool is_new = last_name != test->name();
330  bool is_total = sm.first == "Total";
331  cout << "|" << (is_new ? test->name() : "")
332  << " |" << (is_total ? "**" : "") << sm.first << (is_total ? "**" : "") << " |"
333  << fixed << median << " |" << mean << " |"
334  << stdev << " |" << max << " |";
335 
336  if (best_fps == 90) cout << "90 ![90](https://placehold.it/15/35ff4d/000000?text=+)";
337  else if (best_fps == 60) cout << "60 ![60](https://placehold.it/15/6fe837/000000?text=+)";
338  else if (best_fps == 30) cout << "30 ![30](https://placehold.it/15/82c13e/000000?text=+)";
339  else if (best_fps == 15) cout << "15 ![15](https://placehold.it/15/eff70c/000000?text=+)";
340  else if (best_fps == 6) cout << "6 ![6](https://placehold.it/15/d6a726/000000?text=+)";
341  else cout << "? ![unknown](https://placehold.it/15/d65d26/000000?text=+)";
342 
343  cout << " |" << endl;
344 
345  printed_steps++;
346  last_name = test->name();
347  }
348  }
349  }
350  cout << endl;
351  }
352 
353  return EXIT_SUCCESS;
354 }
355 catch (const error & e)
356 {
357  cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n " << e.what() << endl;
358  return EXIT_FAILURE;
359 }
void init_processing(bool use_glsl=true)
frameset wait_for_frames(unsigned int timeout_ms=RS2_DEFAULT_TIMEOUT) const
volatile void * _ptr
GLuint const GLchar * name
string get_cpu()
The header of the GLFW 3 API.
int main(int argc, char **argv)
GLFWAPI GLFWglproc glfwGetProcAddress(const char *procname)
Returns the address of the specified function for the current context.
Definition: context.c:741
pb_test(std::string name)
GLfloat GLfloat p
Definition: glext.h:12687
const GLfloat * m
Definition: glext.h:6814
void *(* GLADloadproc)(const char *name)
#define GL_RENDERER
frame process(frame f) override
const void * get_data() const
Definition: rs_frame.hpp:545
Definition: cah-model.h:10
#define glFlush
GLsizei const GLchar *const * string
frame process(frame f) override
GLuint GLuint stream
Definition: glext.h:1790
virtual void register_tests(stream_profile stream, vector< shared_ptr< test >> &tests) const =0
e
Definition: rmse.py:177
void sort(sort_type m_sort_type, const std::string &in, const std::string &out)
virtual const std::string & name() const override
def info(name, value, persistent=False)
Definition: test.py:301
const std::string & get_failed_args() const
Definition: rs_types.hpp:117
GLFWAPI int glfwInit(void)
Initializes the GLFW library.
Definition: init.c:198
GLdouble f
std::ostream & cout()
void register_tests(stream_profile stream, vector< shared_ptr< test >> &tests) const override
frame prepare(frame f) override
GLFWAPI void glfwMakeContextCurrent(GLFWwindow *window)
Makes the context of the specified window current for the calling thread.
Definition: context.c:611
#define REGISTER_GL_TEST(x)
virtual frame prepare(frame f)
void keep()
Definition: rs_frame.hpp:437
void enable_stream(rs2_stream stream_type, int stream_index, int width, int height, rs2_format format=RS2_FORMAT_ANY, int framerate=0)
GLAPI int gladLoadGLLoader(GLADloadproc)
Definition: glad/glad.c:1697
gl::uploader _upload
virtual frame finish(frame f)
GLFWAPI GLFWwindow * glfwCreateWindow(int width, int height, const char *title, GLFWmonitor *monitor, GLFWwindow *share)
Creates a window and its associated context.
Definition: window.c:151
rs2_format format() const
Definition: rs_frame.hpp:44
void parse(int argc, const char *const *argv)
Definition: CmdLine.h:433
#define glFinish
gl_test(std::string name)
GLint GLsizei count
#define RS2_API_VERSION_STR
Definition: rs.h:43
#define REGISTER_TEST(x)
#define glGetString
#define GLFW_VISIBLE
Window visibility window hint and attribute.
Definition: glfw3.h:780
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
std::ostream & cerr()
int i
GLuint res
Definition: glext.h:8856
frame finish(frame f) override
Definition: Arg.h:57
#define GL_VERSION
pipeline_profile start()
rs2_stream stream_type() const
Definition: rs_frame.hpp:39
void flush()
GLFWAPI void glfwWindowHint(int hint, int value)
Sets the specified window hint to the desired value.
Definition: window.c:291
const std::string & get_failed_function() const
Definition: rs_types.hpp:112
std::string _name
void register_tests(stream_profile stream, vector< shared_ptr< test >> &tests) const override


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:40