主要问题是计算在 Python 中运行的算法的执行时间,并为在同一数据上每次执行算法获得固定的执行时间。我在每次执行算法时都使用相同的数据。
我正在尝试计算我的算法的执行时间。当我运行我的算法时,它会为每次运行提供不同的执行时间。我认为这是由于我的 CPU 和 RAM 随机分配给算法。我想隔离有限的 CPU 核心和 RAM 以测试我的算法的执行时间。我已经在 Grub 设置中使用“isolcpus”来限制我的 CPU,但它对我没有帮助。也出现了同样问题。
有没有什么方法可以让我的算法在每次运行相同的数据时获得固定的执行时间?
答案1
通常很难获得固定的执行时间,但您可以尝试以下方法来最小化差异:
- 操作系统级别的事情
- 确保 GRUB 设置确实出现在 中
cat /proc/cmdline
。如果没有,请运行sudo update-grub
并重新启动 - 每次启动后,通过运行试运行并在实际运行之前丢弃结果来填充缓存。基本上只需运行两次命令并进行第二次运行。这可确保所有代码和数据都从内存加载到页面缓存中,并
__pycache__
在适当的时候生成,从而消除磁盘访问的变量 - 确保你确实使用以下方式为特定进程设置了 CPU 亲和性
taskset -c <the core you used for isolcpus>
- 关闭不必要的程序并使用 TTY 代替 GUI。如果这不可能,至少使用时
sudo nice -20
将优先级设置为最大。 - 你的最终命令可能看起来像
sudo taskset -c 1 nice -n -20 python ./my_algorithm.py
- 确保 GRUB 设置确实出现在 中
- 编程层面的事情
- 消除代码中的所有打印语句。许多构建系统的瓶颈在于运行它们的终端处理控制台输出的速度
- 避免使用随机或非确定性算法。许多随机数生成器都依赖于当前系统时间,因此请调用
setseed
或类似方法。某些排序算法(如快速排序)会随机选择基准,因此请使用确定性算法(如合并排序)。这些算法不会产生很大影响,但如果您坚持,可以设置系统时间。 - 在现代 Intel/AMD CPU 上,固定执行时间几乎是不可能的,甚至密码学博士学位也可能无法实现。以下是一些启发性的文章https://en.wikipedia.org/wiki/Reproducible_builds和https://en.wikipedia.org/wiki/Timing_attack。但是,您可以考虑在较旧的单核 Raspberry Pi 上安装 Ubuntu。使用相同的技术,这会提供相对固定的执行时间(Arduino 将立即完全修复)
- 硬件层面的事情:
- 内存应该无关紧要。只需重新启动,不要打开额外的程序。您的内存速度应由 BIOS 设置为恒定速度(尽管某些 BIOS 存在在挂起时更改该速度的错误,因此不要这样做)。高级主题是内存 cgroup 和 NUMA,但它们不是必需的。
- 将 CPU 频率设置为 CPU 的最低非加速频率。这样 CPU 就无需检查温度或电流是否适合在高频率下运行。由于 indicator-cpufreq 现在可能不起作用,因此您应该使用 sudo 和 bash 将一个数字回显到
/sys/devices/system/cpu/cpu*/cpufreq/scaling_{max_freq,min_freq,setspeed}
。将调节器设置为 或powersave
,performance
以便更有可能坚持该数字 - 在 BIOS 中禁用超线程,否则你需要调整你的任务集和 isolcpus 以适应它
- 如果使用笔记本电脑,请确保它不会过热和热节流
但是,为什么您希望算法在固定的时间内完成?您可能希望为您的(算法,数据)对报告一个数字。在这种情况下,通常会在多次运行中进行采样。像https://packages.ubuntu.com/jammy/utils/hyperfine将确定所需的运行次数,并输出一个稳定的数字。如果失败,它将给出标准偏差。此外,如果您的算法运行时间远少于几秒钟,则应for
在 Python 端将其包装在循环中。