o-du/phy
Intel O-RAN/X-RAN Generated Doxygen Documentation
common.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 *
3 * Copyright (c) 2019 Intel.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *******************************************************************************/
18 
19 
20 #include <cmath>
21 #include <fstream>
22 #include <numeric>
23 
24 #ifndef _WIN64
25 #include <unistd.h>
26 #include <sys/syscall.h>
27 #else
28 #include <Windows.h>
29 #endif
30 
31 #include "common.hpp"
32 
33 #ifndef CPU_ID
34 #define CPU_ID 4
35 #endif
36 
37 /* Required to avoid linker errors */
39 std::string KernelTests::test_type;
40 unsigned long KernelTests::tsc;
41 
42 
46 
47 int bind_to_cpu(const unsigned cpu)
48 {
49 #ifndef _WIN64
50  const auto pid = syscall(SYS_gettid);
51  cpu_set_t mask {};
52  CPU_ZERO(&mask);
53  CPU_SET(cpu, &mask);
54  return sched_setaffinity(__pid_t(pid), sizeof(mask), &mask);
55 #else
56  return -1;
57 #endif
58 }
59 
60 std::pair<double, double> calculate_statistics(const std::vector<long> values)
61 {
62  const auto sum = std::accumulate(values.begin(), values.end(), 0L);
63 
64  const auto number_of_iterations = BenchmarkParameters::repetition *
66 
67  const auto mean = sum / (double) number_of_iterations;
68 
69  auto stddev_accumulator = 0.0;
70  for (auto v : values)
71  stddev_accumulator = pow((v / BenchmarkParameters::loop) - mean, 2);
72 
73  const auto stddev = sqrt(stddev_accumulator / BenchmarkParameters::repetition);
74 
75  return {mean, stddev};
76 }
77 
78 std::vector<unsigned> get_sequence(const unsigned number)
79 {
80  std::vector<unsigned> sequence(number);
81  std::iota(sequence.begin(), sequence.end(), 0);
82 
83  return sequence;
84 }
85 
86 char* read_data_to_aligned_array(const std::string &filename)
87 {
88  std::ifstream input_stream(filename, std::ios::binary);
89 
90  std::vector<char> buffer((std::istreambuf_iterator<char>(input_stream)),
91  std::istreambuf_iterator<char>());
92 
93  if(buffer.size() == 0)
95 
96  auto aligned_buffer = aligned_malloc<char>((int) buffer.size(), 64);
97 
98  if(aligned_buffer == nullptr)
99  throw std::runtime_error("Failed to allocate memory for the test vector!");
100 
101  std::copy(buffer.begin(), buffer.end(), aligned_buffer);
102 
103  return aligned_buffer;
104 }
105 
106 json read_json_from_file(const std::string &filename)
107 {
108  json result;
109 
110  std::ifstream json_stream(filename);
111  if(!json_stream.is_open())
113 
114  json_stream >> result;
115 
116  return result;
117 }
118 
119 unsigned long tsc_recovery()
120 {
121 #ifndef _WIN64
122  constexpr auto ns_per_sec = 1E9;
123 
124  struct timespec sleeptime = {.tv_nsec = __syscall_slong_t(5E8) };
125 
126  struct timespec t_start, t_end;
127 
128  if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0)
129  {
130  unsigned long start = tsc_tick();
131 
132  nanosleep(&sleeptime,NULL);
133  clock_gettime(CLOCK_MONOTONIC_RAW, &t_end);
134 
135  unsigned long end = tsc_tick();
136 
137  unsigned long ns = (unsigned long)((t_end.tv_sec - t_start.tv_sec) * ns_per_sec + t_end.tv_nsec - t_start.tv_nsec);
138 
139  double secs = (double) ns / ns_per_sec;
140 
141  unsigned long resolution_timer = (unsigned long)((end - start)/secs);
142  unsigned long tick_per_usec = (resolution_timer / 1000000);
143 
144  std::cout << "[----------] System clock (rdtsc) resolution " << resolution_timer << " [Hz]" << std::endl;
145  std::cout << "[----------] Ticks per us " << tick_per_usec << std::endl;
146 
147  return tick_per_usec;
148  }
149 #else
150 
151  LARGE_INTEGER tick_per_sec;
152  QueryPerformanceFrequency(&tick_per_sec);
153 
154  std::cout << "[----------] System clock (rdtsc) resolution unknown" << std::endl;
155  std::cout << "[----------] Ticks per us " << (tick_per_sec.QuadPart / 1000000) << std::endl;
156  return (unsigned long) tick_per_sec.QuadPart;
157 
158 #endif
159  return 0;
160 }
161 
162 unsigned long tsc_tick()
163 {
164 #ifndef _WIN64
165  unsigned long hi, lo;
166 
167  __asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
168 
169  return lo | (hi << 32);
170 #else
171  return 0;
172 #endif
173 }
174 
175 void KernelTests::print_and_store_results(const std::string &isa, const std::string &parameters,
176  const std::string &module_name, const std::string &test_name,
177  const std::string &unit, const int para_factor,
178  const double mean, const double stddev)
179 {
180  std::cout << "[----------] " << "Mean" << " = " << std::fixed << mean << " us" << std::endl;
181  std::cout << "[----------] " << "Stddev" << " = " << stddev << " us" << std::endl;
182 
183 #ifndef _WIN64
184  /* Two properties below should uniquely identify a test case */
185  RecordProperty("kernelname", module_name);
186  RecordProperty("parameters", parameters);
187 
188  RecordProperty("isa", isa);
189  RecordProperty("unit", unit);
190  RecordProperty("parallelization_factor", para_factor);
191 
192  RecordProperty("mean", std::to_string(mean));
193  RecordProperty("stddev", std::to_string(stddev));
194 #endif
195 }
json read_json_from_file(const std::string &filename)
Read JSON from the given file.
Definition: common.cpp:106
a class to store JSON values
Definition: json.hpp:1016
static unsigned cpu_id
Definition: common.hpp:68
static json conf
Definition: common.hpp:159
static std::string test_type
Definition: common.hpp:160
char * read_data_to_aligned_array(const std::string &filename)
Read binary data from the file.
Definition: common.cpp:86
static long repetition
Definition: common.hpp:66
std::pair< double, double > calculate_statistics(const std::vector< long > values)
Calculate the mean and variance from the result of the run_benchmark.
Definition: common.cpp:60
unsigned long tsc_recovery()
Measure the TSC on the machine.
Definition: common.cpp:119
const std::string module_name
static long loop
Definition: common.hpp:67
int bind_to_cpu(const unsigned cpu)
Attach current process to the selected core.
Definition: common.cpp:47
unsigned long tsc_tick()
Return the current value of the TSC.
Definition: common.cpp:162
uint64_t tick_per_usec
Definition: sample-app.c:64
#define CPU_ID
Definition: common.cpp:34
std::vector< unsigned > get_sequence(const unsigned number)
For a given number return sequence of number from 0 to number - 1.
Definition: common.cpp:78