我以如下方式实现了100%的一致结果:
- 使用MS-DOS设置Bochs。
- 设置您的工具链以针对MS-DOS
— 或者 —
- 将您的工具链设置为针对32位Windows
- 在Bochs中安装HX-DOS extender。
- 如果需要,请修改您的工具包标准库/运行时,并删除需要在HX-DOS中未实现的Windows API的功能。在尝试运行程序时,扩展器将打印未实现API的列表。
- 将基准测试中的周期数减少几个数量级。
- 用汇编指令
cli
/ sti
包装基准测试代码(请注意,在此更改后,二进制文件将无法在现代操作系统上运行)。
- 如果您还没有,使您的基准测试使用
rdtsc
差值进行计时。样本应在cli
…sti
指令内。
- 在Bochs中运行它!
![Bochs screenshot](https://istack.dev59.com/0lqi8.webp)
结果似乎完全是确定性的,但并不是对整体性能的准确评估(有关详细信息,请参见 Osman Turan 答案下的讨论)。
作为额外提示,以下是与Bochs共享文件的简单方法(这样您就不必每次卸载/重建/重新安装软盘映像):
在Windows上,Bochs将锁定软盘映像文件,但该文件仍以共享写模式打开。这意味着您无法覆盖该文件,但可以向其中写入内容。(我认为*nix操作系统可能会导致覆盖创建一个新文件,就文件描述符而言。)诀窍是使用
dd
。我设置了以下批处理脚本:
... benchmark build commands here ...
copy /Y C:\Path\To\Benchmark\Project\test2dos.exe floppy\test2.exe
bfi -t=288 -f=floppysrc.img floppy
dd if=floppysrc.img of=floppy.img
bfi
是Bart的制作软盘镜像工具。
然后,在Bochs中挂载floppy.img
即可。
奖励小贴士#2:为了避免在Bochs中每次手动启动基准测试,可以在软盘目录中放置一个空的go.txt
文件,并在Bochs中运行此批处理文件:
@echo off
A:
:loop
choice /T:y,1 > nul
if not exist go.txt goto loop
del go.txt
echo ---------------------------------------------------
test2
goto loop
每当检测到新的软盘映像,它都会启动测试程序。这样,您可以在一个脚本中自动化基准测试运行。
更新:该方法并不是非常可靠。有时候,只要重新排序一些测试,时间会变化多达200%(当使用原始问题中描述的方法在真实硬件上运行时,这些时间变化并未观察到)。
rdtsc
返回的计数器更接近经过的时间,而不是周期计数。我不确定在Core i7上禁用SpeedStep是否足以抵消这种影响。 - Vladimir Panteleev