Я должен использовать функцию clock_gettime() для оценки и профилирования других операций, а также для домашней работы, поэтому я не могу использовать профилировщик и писать собственный код.
То, как я это делаю, выглядит следующим образом:
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,&begin);
for(int i=0;i<=n;i++)
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
cout<<(end.tv_nsec-begin.tv_nsec)/n; //time per clock_gettime()
Проблема заключается в том, что при n = 100 выход равен: 370,63 нс, когда n = 100000, выход: 330 нс, когда n = 1000000, выход: 260 нс, n = 10000000, выход: 55 нс,.... продолжает уменьшать,
Я понимаю, что это происходит из-за кэширования команд, но я не знаю, как справиться с этим при профилировании. Потому что, например, когда я оцениваю время вызова функции с помощью gettime, как узнать, сколько времени используется для использования в gettime?
Будет ли хорошая оценка всех этих ценностей взвешенной? (Я могу запустить операцию, я хочу, чтобы такое же количество раз, принять взвешенное значение этого, вычесть взвешенное среднее времени gettime и получить хорошую оценку операции независимо от кеширования?)
Любые предложения приветствуются.
Заранее спасибо.
Когда вы вычисляете разницу во времени: (end.tv_nsec-begin.tv_nsec)/n
Вы учитываете только наносекундную часть прошедшего времени. Вы также должны учитывать секунды, так как поле tv_nsec
отражает только дробную часть секунды:
int64_t end_ns = ((int64_t)end.tv_sec * 1000000000) + end.tv_nsec;
int64_t begin_ns = ((int64_t)begin.tv_sec * 1000000000) + begin.tv_nsec;
int64_t elapsed_ns = end_ns - begin_ns;
На самом деле, с вашим текущим кодом вы иногда должны получать отрицательные результаты, когда часть наносекунд end
обернута вокруг и меньше, чем begin
наносекундной части.
Исправьте это, и вы сможете наблюдать гораздо более последовательные результаты.
Измените: ради полноты, здесь код, который я использовал для своих тестов, который дает мне очень последовательные результаты (от 280 до 300 нс на звонок, любое количество итераций, которые я использую):
int main() {
const int loops = 100000000;
struct timespec begin;
struct timespec end;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &begin);
for(int i = 0; i < loops; i++)
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
int64_t end_ns = ((int64_t)end.tv_sec * 1000000000) + end.tv_nsec;
int64_t begin_ns = ((int64_t)begin.tv_sec * 1000000000) + begin.tv_nsec;
int64_t elapsed_ns = end_ns - begin_ns;
int64_t ns_per_call = elapsed_ns / loops;
std::cout << ns_per_call << std::endl;
}