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 | |
11 | namespace taichi::lang { |
12 | |
13 | CompileConfig default_compile_config; |
14 | std::string compiled_lib_dir; |
15 | std::string runtime_tmp_dir; |
16 | |
17 | std::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 | |
36 | real 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 | |
50 | real default_measurement_time = 1; |
51 | |
52 | real 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 | |
87 | bool 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 |
104 | namespace taichi { |
105 | void 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 | |