Измерение суммы процессорного времени, потраченного частью кода, в C на Unix/Linux

Может синхронизировать () использоваться в качестве надежного API для измерения времени, потраченного ЦП для выполнения отрывка кода? При проверке с помощью времен () / часы (), оба, кажется, не измеряют процессорное время, потраченное точно.

Во-первых, API могут показать () / время () использоваться для измерения времени выполнения функции/отрывка кода, как дали в примере ниже? Существует ли лучшая и надежная альтернатива? Механизм должен работать над Linux, HP-UX, IBM-AIX и Sun Solaris, поскольку мы должны иметь размеры (&& выдерживают сравнение), производительность части кода всех этих платформ.

Любезно предложите. Кроме того, сообщите мне, пропускаю ли что-либо тривиальное.

bbb@m_001:/tmp/kk1$ ./perf_clock 102400
{clock(): S          0 E          0 D    0.0000000000}
bbb@m_001:/tmp/kk1$ ./perf_clock 204800
{clock(): S          0 E      10000 D    0.0100000000}
bbb@m_001:/tmp/kk1$ cat perf_clock.c

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

void test_clock(char* sbuf, int* len){
    clock_t start, end; int i=0;
    start = clock();
    while(i++ < 500) memset((char*)sbuf,0,*len);
    end = clock();
    printf("{clock(): S %10lu E %10lu D %15.10f}\n",
        start,end,(end-start)/(double) CLOCKS_PER_SEC);
}
int main(int argc,char* argv[])
{
        int len=atoi(argv[1]);
        char *sbuf=(char*)malloc(len);
        test_clock(sbuf,&len);
        free(sbuf); return 0;
}

Результаты, кажется, говорят что memset () блок на 100 КБ, 500 раз, нет никакого проведенного времени. Или это говорит, что это не измеримо в микросекундах?

На самом деле это не memset (), но другая функция [который готовит огромную структуру, измеренную, приблизительно 1 МБ, mallocs копия этой структуры, делает DB Oracle, выбирают и заполняют эти структуры с данными из DB], который пытается иметь размеры. Даже это показывает 0 галочек, и именно это сохранил меня смущенным.

Спасибо!

6
задан raghava 11 January 2010 в 12:21
поделиться

6 ответов

На последних версиях Linux (*) вы можете получить эту информацию из файловой системы /proc. В файле /proc/PID/stat 14-я запись содержит количество jiffies, используемое в коде пользователя, а 15-я - количество jiffies, используемое в системном коде.

Если вы хотите видеть данные по каждой теме, вам следует обратиться к файлу /proc/PID/task/TID/stat.

Для преобразования микросекунд в микросекунды можно использовать следующее:

define USEC_PER_SEC         1000000UL

long long jiffies_to_microsecond(long long jiffies)
{
    long hz = sysconf(_SC_CLK_TCK);
    if (hz <= USEC_PER_SEC && !(USEC_PER_SEC % hz))
    {
        return (USEC_PER_SEC / hz) * jiffies;
    }
    else if (hz > USEC_PER_SEC && !(hz % USEC_PER_SEC))
    {
        return (jiffies + (hz / USEC_PER_SEC) - 1) / (hz / USEC_PER_SEC);
    }
    else
    {
        return (jiffies * USEC_PER_SEC) / hz;
    }
}

Если вас интересует только статистика по каждому процессу, то getrusage проще. Но если вы хотите быть готовы к этому на основе per-thread, то эта техника лучше, чем имя файла, код будет идентичен получению данных для каждого процесса или для каждой цепочки.

* - Я не знаю точно, когда был введен статический файл. Вам нужно будет проверить, что он есть в вашей системе.

7
ответ дан 8 December 2019 в 13:46
поделиться

Я бы попробую с GetRusage и проверять систему и пользовательское время.

Также проверьте с GetTimeOfDay , чтобы сравнить со временем настенного часа.

5
ответ дан 8 December 2019 в 13:46
поделиться

Я бы попытался сопоставить время с временем Shell's командой , как проверка здравоохранения.

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

Я бы также оспорить, что 10 МБ, возможно, в кэш-памяти действительно будет 1,25 или 2,5 млн. Рублей операций процессора, поскольку MEMSET, безусловно, пишет в 4-байтовых или 8-байтовых количествах. Хотя я скорее сомневаюсь, что это может быть сделано менее чем в микросекунде, поскольку магазины немного дороги, и 100K добавляет некоторое давление кэша L1, вы говорите о не намного более чем одной операции на наносекунду, что не так уж сложно поддерживать Multi-GHZ CPU.

Один воображает, что 600 нс охватывают до 1 часа галочка, но я бы тоже беспокоился об этом.

4
ответ дан 8 December 2019 в 13:46
поделиться

вы можете использовать clock_t для получения количества тиков процессора с момента запуска программы.

или Вы можете использовать команду linux time. например: time [program] [arguments]

.
1
ответ дан 8 December 2019 в 13:46
поделиться

Использование ресурсов процесса / потока обновляется только по ОС только периодически. Это полностью возможно для фрагмента кода, чтобы завершить до следующего обновления, создаваемого таким образом, создающим нулевое использование ресурсов. Ничего не могу сказать о HP или AIX, будет направить вас к Performance Solaris и инструменты Книга для Солнца. Для Linux вы хотите посмотреть oprofile и новее Perf Tool . На полученной стороне Valgrind будет иметь большую помощь.

0
ответ дан 8 December 2019 в 13:46
поделиться

Некоторая информация на странице HP о таймерах высокого разрешения. Также этот же трюк _Asm_mov_from_ar (_AREG_ITC); используется в http://www.fftw.org/cycle.h.

Должны подтвердить, действительно ли это может быть решением.

Пример программы, протестированной на HP-UX 11.31:

bbb@m_001/tmp/prof > ./perf_ticks 1024
ticks-memset {func [1401.000000] inline [30.000000]} noop [9.000000]
bbb@m_001/tmp/prof > cat perf_ticks.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "cycle.h" /* one from http://www.fftw.org/cycle.h */
void test_ticks(char* sbuf, int* len){
    memset((char*)sbuf,0,*len);
}
int main(int argc,char* argv[]){
        int len=atoi(argv[1]);
        char *sbuf=(char*)malloc(len);
        ticks t1,t2,t3,t4,t5,t6;
        t1 =getticks(); test_ticks(sbuf,&len); t2 =getticks();
        t3 =getticks(); memset((char*)sbuf,0,len); t4 =getticks();
        t5=getticks();;t6=getticks();
        printf("ticks-memset {func [%llf] inline [%llf]} noop [%llf]\n",
                          elapsed(t2,t1),elapsed(t4,t3),elapsed(t6,t5));
        free(sbuf); return 0;
}
bbb@m_001/tmp/prof >
0
ответ дан 8 December 2019 в 13:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: