测量工具的时钟周期不一致,这种不一致的周期究竟来自哪里?

如何解决测量工具的时钟周期不一致,这种不一致的周期究竟来自哪里?

我花了很多时间来测量给定指令的精确时钟周期,部分代码是用 C 编写的。但是,我永远无法准确测量运行时需要多少个周期,我使用了 PAPI,“rtdsc”硬件计数器,时钟(),带有“CLOCK_REALTIME”的clock_gettime。然而,对于每次运行,我得到不同的数字,(我不想将程序迭代超过 100000 次并获得平均值,在我的情况下不起作用!即使有效,平均值仍然是在我看来不是确切的方式),

我很惊讶没有精确的测量工具,因为我们确切地知道有多少指令,我们怎么可能没有合适的测量工具!

我用 oprofile 和 vtune(里面使用了 pref)进行了分析,我确切地知道发生了什么,但我如何才能准确地测量它?恐怕没有办法!

对于下面的示例代码,调用斐波那契函数,没办法得到准确的周期数!

#include <stdio.h>
#include <time.h>
#include <math.h>
#include <stdint.h>

#ifdef PAPI
#include <papi.h>
#endif

uint64_t fib(int n) { return n < 2 ? (uint64_t)n : fib(n-1) + fib(n-2); }

#define rdtscll(val) {                                           \
    unsigned int __a,__d;                                        \
    asm volatile("rdtsc" : "=a" (__a),"=d" (__d));              \
    (val) = ((unsigned long)__a) | (((unsigned long)__d)<<32);   \
}

int main(int argc,char **argv)
{
    struct timespec tv;
    long long start,stop;
#ifdef PAPI
    //  gcc test.c -I/${PAPI_DIR}/include -L/${PAPI_DIR}/lib -O3 -o test -lpapi
    if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT)
        exit(1);
    start = PAPI_get_real_cyc();
    #ifdef math
    fib(10);
    #endif  
    stop = PAPI_get_real_cyc();
    printf("total cycles : %lld\n",stop-start);
#endif  
#ifdef clk
    start = clock();
    #ifdef math
    fib(10);
    #endif  
    stop = clock();
    printf("total cycles : %lld\n",stop-start);
#endif
#ifdef Wtime
    clock_gettime(CLOCK_REALTIME,&tv);
    start= (tv.tv_sec) * 1000000000 + (tv.tv_nsec);
    #ifdef math
    fib(10);
    #endif  
    clock_gettime(CLOCK_REALTIME,&tv);
    stop= (tv.tv_sec) * 1000000000 + (tv.tv_nsec);
    printf("total time : %lld\n",stop-start);
#endif
#ifdef hardware_counter
    rdtscll(start);
    #ifdef math
    fib(10);
    #endif  
    rdtscll(stop);  
    printf("total cycles : %lld\n",stop-start);
#endif
    return 0;
}

例如,我将其中一些的 objdump 输出放在这里 rtdsc:

0000000000400450 <main>:
  400450:   48 83 ec 08             sub    $0x8,%rsp
  400454:   0f 31                   rdtsc  
  400456:   89 c0                   mov    %eax,%eax
  400458:   48 c1 e2 20             shl    $0x20,%rdx
  40045c:   48 09 c2                or     %rax,%rdx
  40045f:   b8 09 00 00 00          mov    $0x9,%eax
  400464:   49 89 d3                mov    %rdx,%r11
  400467:   83 f8 01                cmp    $0x1,%eax
  40046a:   7e 5c                   jle    4004c8 <main+0x78>
  40046c:   44 8d 48 fe             lea    -0x2(%rax),%r9d
  400470:   44 8d 50 fd             lea    -0x3(%rax),%r10d
  400474:   44 8d 40 ff             lea    -0x1(%rax),%r8d
  400478:   44 89 c8                mov    %r9d,%eax
  40047b:   83 e0 fe                and    $0xfffffffe,%eax
  40047e:   41 29 c2                sub    %eax,%r10d
  400481:   44 89 c7                mov    %r8d,%edi
  400484:   e8 37 01 00 00          callq  4005c0 <xfib>
  400489:   41 83 e8 02             sub    $0x2,%r8d
  40048d:   45 39 d0                cmp    %r10d,%r8d
  400490:   75 ef                   jne    400481 <main+0x31>
  400492:   41 83 f9 ff             cmp    $0xffffffff,%r9d
  400496:   44 89 c8                mov    %r9d,%eax
  400499:   75 cc                   jne    400467 <main+0x17>
  40049b:   0f 31                   rdtsc  
  40049d:   89 c0                   mov    %eax,%eax
  40049f:   48 c1 e2 20             shl    $0x20,%rdx
  4004a3:   be 24 0a 40 00          mov    $0x400a24,%esi
  4004a8:   48 09 c2                or     %rax,%rdx
  4004ab:   bf 01 00 00 00          mov    $0x1,%edi
  4004b0:   31 c0                   xor    %eax,%eax
  4004b2:   4c 29 da                sub    %r11,%rdx
  4004b5:   e8 76 ff ff ff          callq  400430 <__printf_chk@plt>
  4004ba:   31 c0                   xor    %eax,%eax
  4004bc:   48 83 c4 08             add    $0x8,%rsp
  4004c0:   c3                      retq   
  4004c1:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)
  4004c8:   44 8d 48 fe             lea    -0x2(%rax),%r9d
  4004cc:   41 83 f9 ff             cmp    $0xffffffff,%r9d
  4004d0:   44 89 c8                mov    %r9d,%eax
  4004d3:   75 92                   jne    400467 <main+0x17>
  4004d5:   eb c4                   jmp    40049b <main+0x4b>
  4004d7:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  4004de:   00 00 

在不调用另一个库、标准输出等的情况下,有什么方法可以准确和一致地测量计算机在一部分代码之间使用的时钟周期数?

感谢您的帮助,

编辑: 感谢大家的评论,关于框架,我在运行 ubuntu 16.04 和 ubuntu 18.04 的物理机上使用 x86_64 和 aarch64。在 aarch64 上的 PAPI 情况下无法通过验证测试,所以我跳过了 PAPI。但是,我也使用“perf”尝试了这个主题,但结果相同, 性能循环计数器 -> https://stackoverflow.com/a/64898073/3101659

我认为这与计算机体系结构的基础有关,在冯诺依曼机器中,使用“随机内存访问”、“brach 预测”和其他东西是我们无法在我们的程序中预测和实现相同周期的原因. 如果我在 FPGA 设备上使用 HLS 运行此程序,我可以准确地测量设备逐个周期使用的周期数,而在基于冯诺依曼的机器等传统机器上,这是不可能的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res