Один из вариантов - использовать инструкцию rdtsc
через функцию __builtin_ia32_rdtsc
.На современных процессорах Intel rdtsc
работает на базовой тактовой частоте на любой частоте процессора, поэтому вы можете преобразовать счетчик в наносекунды, разделив счетчик на базовую (не повышающую) частоту процессора в ГГц:
#include <regex>
#include <string>
#include <fstream>
#include <iostream>
double cpu_base_frequency() {
std::regex re("model name\\s*:[^@]+@\\s*([0-9.]+)\\s*GHz");
std::ifstream cpuinfo("/proc/cpuinfo");
std::smatch m;
for(std::string line; getline(cpuinfo, line);) {
regex_match(line, m, re);
if(m.size() == 2)
return std::stod(m[1]);
}
return 1; // Couldn't determine the CPU base frequency. Just count TSC ticks.
}
double const CPU_GHZ_INV = 1 / cpu_base_frequency();
int main() {
auto t0 = __builtin_ia32_rdtsc();
auto t1 = __builtin_ia32_rdtsc();
std::cout << (t1 - t0) * CPU_GHZ_INV << "nsec\n";
}
Более подробная информация из документации Intel:
Постоянное поведение TSC гарантирует, что длительность каждого тактового сигнала одинакова, и поддерживает использование TSC в качестве настенного таймера, даже есличастота ядра процессора меняется.Это архитектурное поведение, продвигающееся вперед.
Инвариант TSC будет работать с постоянной скоростью во всех P-, C- и T-состояниях ACPI.Это архитектурное поведение, движущееся вперед.На процессорах с инвариантной поддержкой TSC ОС может использовать TSC для служб таймера настенных часов (вместо таймеров ACPI или HPET).Чтения TSC намного более эффективны и не требуют дополнительных затрат, связанных с переходом по кольцу или доступом к ресурсу платформы.
Инвариант TSC основан на инвариантном аппаратном обеспечении хронометража (называемом Always RunningТаймер или ART), который работает на тактовой частоте основного кристалла.
Масштабируемая частота шины кодируется в битовом поле MSR_PLATFORM_INFO [15: 8], и номинальная частота TSC может быть определена путем умножения этого числа начастота шины 100 МГц.