1// Definitions of utility functions and enums
2
3#include "taichi/util/lang_util.h"
4
5#include "taichi/math/linalg.h"
6#include "taichi/rhi/arch.h"
7#include "taichi/program/program.h"
8#include "taichi/program/compile_config.h"
9#include "taichi/system/timer.h"
10
11namespace taichi::lang {
12
13CompileConfig default_compile_config;
14std::string compiled_lib_dir;
15std::string runtime_tmp_dir;
16
17std::string runtime_lib_dir() {
18 std::string folder;
19 if (!compiled_lib_dir.empty()) {
20 folder = compiled_lib_dir;
21 } else {
22 auto ti_lib_dir = getenv("TI_LIB_DIR");
23 TI_ERROR_IF(
24 !ti_lib_dir,
25 "If you are running the taichi_cpp_tests please set $TI_LIB_DIR "
26 "to $TAICHI_INSTALL_DIR/_lib/runtime. $TAICHI_INSTALL_DIR can be "
27 "retrieved from taichi.__path__[0] in python. You can also use this "
28 "script to find out $TI_LIB_DIR:\n\n"
29 "python -c \"import os; import taichi as ti; p = "
30 "os.path.join(ti.__path__[0], '_lib', 'runtime'); print(p)\"");
31 folder = std::string(ti_lib_dir);
32 }
33 return folder;
34}
35
36real get_cpu_frequency() {
37 static real cpu_frequency = 0;
38 if (cpu_frequency == 0) {
39 uint64 cycles = Time::get_cycles();
40 Time::sleep(1);
41 uint64 elapsed_cycles = Time::get_cycles() - cycles;
42 auto frequency = real(std::round(elapsed_cycles / 1e8_f64) / 10.0_f64);
43 TI_INFO("CPU frequency = {:.2f} GHz ({} cycles per second)", frequency,
44 elapsed_cycles);
45 cpu_frequency = frequency;
46 }
47 return cpu_frequency;
48}
49
50real default_measurement_time = 1;
51
52real measure_cpe(std::function<void()> target,
53 int64 elements_per_call,
54 real time_second) {
55 if (time_second == 0) {
56 target();
57 return std::numeric_limits<real>::quiet_NaN();
58 }
59 // first make rough estimate of run time.
60 int64 batch_size = 1;
61 while (true) {
62 float64 t = Time::get_time();
63 for (int64 i = 0; i < batch_size; i++) {
64 target();
65 }
66 t = Time::get_time() - t;
67 if (t < 0.05 * time_second) {
68 batch_size *= 2;
69 } else {
70 break;
71 }
72 }
73
74 int64 total_batches = 0;
75 float64 start_t = Time::get_time();
76 while (Time::get_time() - start_t < time_second) {
77 for (int i = 0; i < batch_size; i++) {
78 target();
79 }
80 total_batches += batch_size;
81 }
82 auto elasped_cycles =
83 (Time::get_time() - start_t) * 1e9_f64 * get_cpu_frequency();
84 return elasped_cycles / float64(total_batches * elements_per_call);
85}
86
87bool command_exist(const std::string &command) {
88#if defined(TI_PLATFORM_UNIX)
89 if (std::system(fmt::format("which {} > /dev/null 2>&1", command).c_str())) {
90 return false;
91 } else {
92 return true;
93 }
94#else
95 if (std::system(fmt::format("where {} >nul 2>nul", command).c_str())) {
96 return false;
97 } else {
98 return true;
99 }
100#endif
101}
102
103} // namespace taichi::lang
104namespace taichi {
105void initialize_benchmark() {
106 // CoreState::set_trigger_gdb_when_crash(true);
107 lang::get_cpu_frequency();
108 static bool initialized = false;
109 if (initialized) {
110 return;
111 }
112 initialized = true;
113#if defined(TI_PLATFORM_LINUX)
114 std::ifstream noturbo("/sys/devices/system/cpu/intel_pstate/no_turbo");
115 char c;
116 noturbo >> c;
117 TI_WARN_IF(c != '1',
118 "You seem to be running the benchmark with Intel Turboboost.");
119#endif
120}
121
122} // namespace taichi
123