diff --git a/Utilities/sysinfo.cpp b/Utilities/sysinfo.cpp index e94c9effe8..084593a238 100755 --- a/Utilities/sysinfo.cpp +++ b/Utilities/sysinfo.cpp @@ -131,13 +131,9 @@ std::string utils::get_system_info() fmt::append(result, "%s | %d Threads | %.2f GiB RAM", brand, num_proc, mem_total / (1024.0f * 1024 * 1024)); - if (!has_invariant_tsc()) + if (const ullong tsc_freq = get_tsc_freq()) { - fmt::append(result, " | TSC: Bad"); - } - else if (const ullong tsc_freq = get_tsc_freq()) - { - fmt::append(result, " | TSC: %.02fGHz", tsc_freq / 1000000000.); + fmt::append(result, " | TSC: %.06fGHz", tsc_freq / 1000000000.); } else { @@ -167,7 +163,7 @@ std::string utils::get_system_info() if (has_fma3() || has_fma4()) { result += " | FMA"; - + if (has_fma3() && has_fma4()) { result += "3+4"; @@ -268,15 +264,67 @@ std::string utils::get_OS_version() ullong utils::get_tsc_freq() { + const ullong cal_tsc = []() -> ullong + { + if (!has_invariant_tsc()) + return 0; #ifdef _WIN32 - LARGE_INTEGER freq; - if (!QueryPerformanceFrequency(&freq) || freq.QuadPart > 9'999'999) - return 0; - return freq.QuadPart * 1024; + LARGE_INTEGER freq; + if (!QueryPerformanceFrequency(&freq)) + return 0; + + if (freq.QuadPart <= 9'999'999) + return freq.QuadPart * 1024; + + const ullong timer_freq = freq.QuadPart; + Sleep(1); #else - // TODO - return 0; + const ullong timer_freq = 1'000'000'000; + ullong sec_base = 0; + usleep(200); #endif + + // Calibrate TSC + constexpr int samples = 40; + ullong rdtsc_data[samples]; + ullong timer_data[samples]; + ullong rdtsc_diff[samples - 1]; + ullong timer_diff[samples - 1]; + + for (int i = 0; i < samples; i++) + { + rdtsc_data[i] = __rdtsc(); + if (i > 0) + rdtsc_diff[i - 1] = rdtsc_data[i] - rdtsc_data[i - 1]; +#ifdef _WIN32 + LARGE_INTEGER ctr; + QueryPerformanceCounter(&ctr); + timer_data[i] = ctr.QuadPart; + Sleep(1); +#else + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + if (i == 0) + sec_base = ts.tv_sec; + timer_data[i] = ts.tv_nsec + (ts.tv_sec - sec_base) * 1'000'000'000; + usleep(200); +#endif + if (i > 0) + timer_diff[i - 1] = timer_data[i] - timer_data[i - 1]; + } + + // Compute average TSC + ullong acc = 0; + for (int i = 0; i < samples - 1; i++) + { + acc += rdtsc_diff[i] * timer_freq / timer_diff[i]; + } + + // Rounding + return acc / (samples - 1); + }(); + + return cal_tsc; } u64 utils::get_total_memory()