mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
Implement TSC calibration
Try to get rough TSC frequency by sampling it.
This commit is contained in:
parent
b6e52ad975
commit
15f01a1bf6
1 changed files with 61 additions and 13 deletions
|
@ -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()
|
||||
|
|
Loading…
Add table
Reference in a new issue