1

我有下一个简单的功能,以便按进程测量计算时间:

double get_cpu_time()
{
  //LINUX      
  const static int64_t NANOS_PER_SEC = 1000000000L;
  struct timespec time;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
  return (((int64_t) time.tv_sec) * NANOS_PER_SEC) + ((int64_t) time.tv_nsec);

}


ini_time = get_cepu_time();

//intesive computation code

end_time = get_cepu_time();


end_time = end_time - ini_time

;

该函数返回每个过程的计算时间,在一个简单的等式中可以如下:

Tcomp = Tcpu + Taccmen => inst * ILP + #miss cache * 延迟时间

有趣的是只获取 Tcpu 时间(执行指令的时间,不考虑查找数据的时间),你知道任何函数来获取这个时间,或者返回内存访问时间的函数,那么我可以 sustract(tcomp - 塔克梅姆)

此致,

4

2 回答 2

3

使用perflinux 上的命令来获取这种性能数据。

例如,在 x86 平台上

perf stat -B sleep 5

Performance counter stats for 'sleep 5':

      0.344308 task-clock                #    0.000 CPUs utilized          
             1 context-switches          #    0.003 M/sec                  
             0 CPU-migrations            #    0.000 M/sec                  
           154 page-faults               #    0.447 M/sec                  
        977183 cycles                    #    2.838 GHz                    
        586878 stalled-cycles-frontend   #   60.06% frontend cycles idle   
        430497 stalled-cycles-backend    #   44.05% backend  cycles idle   
        720815 instructions              #    0.74  insns per cycle        
                                         #    0.81  stalled cycles per insn
        152217 branches                  #  442.095 M/sec                  
          7646 branch-misses             #    5.02% of all branches        

   5.002763199 seconds time elapsed

这将运行sleep 5命令并为您提供从 x86 处理器上的性能计数器收集的详细信息。您感兴趣的是查看执行的指令计数和周期数,该比率是它为您计算的每个周期的指令,它还告诉您处理器平均每条指令停顿了多少个周期。要获得缓存引用的数量和未命中的数量,您需要明确要求

perf stat -B -e cache-references,cache-misses,cycles,instructions

请参阅为什么 perf 不报告缓存未命中?

于 2013-02-06T22:35:38.153 回答
0

...评论空间用完了...

如果您对分析算法感兴趣,并且想要抽象出内存访问时间,那么您将不得不将您的测试数据直接放在通用寄存器中......这样就可以组装了。但是如果你对堆栈内存访问时间没问题,那么你可以存根一些堆栈变量并使用它们......你可能真的不需要做任何这些,只需做

struct timespec time;
struct timespec time2;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time); 
something();
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);

然后担心完成后解码时间......你不想在你的get time函数中做一堆计算......如果你真的试图获得有意义的数据,那会导致问题......

如果您不担心时间,而是担心计算复杂性和指令数量,那么您应该编译为汇编并尝试遵循它......(有时说起来容易做起来难......)

    void simple()
{
    int i = 0;
    for (int j=0;j<25;j++)
        i+=j;
}

//-> gcc -S -std=c99 simple.c

_simple:

Leh_func_begin1:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    movl    $0, -4(%rbp)
    movl    $0, -8(%rbp)
    jmp LBB1_2
LBB1_1:
    movl    -4(%rbp), %eax
    movl    -8(%rbp), %ecx
    addl    %ecx, %eax
    movl    %eax, -4(%rbp)
    movl    -8(%rbp), %eax
    addl    $1, %eax
    movl    %eax, -8(%rbp)
LBB1_2:
    movl    -8(%rbp), %eax
    cmpl    $24, %eax
    jle LBB1_1
    popq    %rbp
    ret
Leh_func_end1:

你可以理解它LBB1_2:对应于 for 循环的条件部分,然后跳回到LBB1_1:for 循环的内部,然后是 for 循环的增量部分,然后LBB1_2:再次下降到......凉爽的。

于 2013-02-06T22:54:43.447 回答