Два последовательных std :: chrono :: high_resolution_clock :: now () дают разницу ~ 270нс - PullRequest
0 голосов
/ 15 марта 2019

Я хочу измерить продолжительность фрагмента кода с часами std::chrono, но это кажется слишком тяжелым, чтобы измерить что-то, что длится наносекунды. Эта программа:

#include <cstdio>
#include <chrono>

int main() {
    using clock = std::chrono::high_resolution_clock;

    // try several times
    for (int i = 0; i < 5; i++) {
        // two consequent now() here, one right after another without anything in between
        printf("%dns\n", (int)std::chrono::duration_cast<std::chrono::nanoseconds>(clock::now() - clock::now()).count());
    }
    return 0;
}

Всегда дает мне около 100-300 нс. Это из-за двух системных вызовов? Возможно ли иметь меньшую продолжительность между двумя сейчас ()? Спасибо!

Среда: Linux Ubuntu 18.04, ядро ​​4.18, средняя загрузка низкая, stdlib связан динамически.

Ответы [ 3 ]

2 голосов
/ 15 марта 2019

Если вы хотите измерить длительность очень быстрых фрагментов кода, обычно рекомендуется запускать их несколько раз и брать среднее время всех запусков, то ~ 200 нс, которые вы упомянули, будут незначительными, поскольку они распределены по все работает.

Пример:

#include <cstdio>
#include <chrono>
using clock = std::chrono::high_resolution_clock;

auto start = clock::now();
int n = 10000; // adjust depending on the expected runtime of your code
for (unsigned int i = 0; i < n; ++i)
    functionYouWantToTime();
auto result =
    std::chrono::duration_cast<std::chrono::nanoseconds>(start - clock::now()).count() / n;
1 голос
/ 15 марта 2019

Только не используйте таймеры для измерения наносекунд. Вместо этого используйте такты процессора - на любом современном оборудовании, чтобы беспокоиться о наносекундах, такты процессора монотонны, устойчивы и синхронизированы между ядрами.

К сожалению, C ++ не предоставляет тактовую частоту процессора, поэтому вам придется использовать инструкцию RDTSC напрямую (она может быть красиво обернута во встроенную функцию или вы можете использовать встроенные функции компилятора). Различие в тактах процессора также может быть преобразовано во время, если вы этого пожелаете (используя частоту процессора), но обычно для таких тестов с малой задержкой это не нужно.

1 голос
/ 15 марта 2019

Используйте команду rdtsc для измерения времени с максимальным разрешением и минимально возможными издержками:

#include <iostream>
#include <cstdint>

int main() {
    uint64_t a = __builtin_ia32_rdtsc();
    uint64_t b = __builtin_ia32_rdtsc();
    std::cout << b - a << " cpu cycles\n";
}

Вывод:

19 cpu cycles

Для преобразованияциклы в наносекунды делят циклы на базовую частоту процессора в ГГц.Например, для i7-7700k с тактовой частотой 4,2 ГГц делить на 4,2.

TSC - это глобальный счетчик ЦП, общий для всех ядер.

Современные ЦП имеют постоянный TSC, который имеет одинаковые значенияСкорость независимо от текущей частоты процессора и повышения.Ищите constant_tsc в /proc/cpuinfo, flags поле.

Также обратите внимание, что __builtin_ia32_rdtsc более эффективен, чем встроенная сборка, см. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48877

...