如何以编程方式禁用硬件预取?

Posted

技术标签:

【中文标题】如何以编程方式禁用硬件预取?【英文标题】:How do I programmatically disable hardware prefetching? 【发布时间】:2010-10-21 12:10:17 【问题描述】:

我想以编程方式禁用硬件预取。

来自Optimizing Application Performance on Intel® Core™ Microarchitecture Using Hardware-Implemented Prefetchers 和 How to Choose between Hardware and Software Prefetch on 32-Bit Intel® Architecture, 我需要更新 MSR 以禁用硬件预取。

这是一个相关的sn-p:

"DPL Prefetch 和 L2 Streaming Prefetch 设置也可以通过编程方式更改 通过编写设备驱动程序实用程序来更改IA32_MISC_ENABLE 中的位 注册——MSR 0x1A0。这样的实用程序提供了启用或禁用预取的能力 无需任何服务器停机时间的机制。

下表显示了IA32_MISC_ENABLE MSR 中为控制DPL 和L2 流式预取而必须更改的位:

Prefetcher Type MSR (0x1A0) Bit Value 
DPL (Hardware Prefetch) Bit 9 0 = Enable 1 = Disable 
L2 Streamer (Adjacent Cache Line Prefetch) Bit 19 0 = Enable 1 = Disable"

我尝试使用http://etallen.com/msr.html,但这不起作用。 我也尝试直接在asm/msr.h 中使用wrmsr,但是会出现段错误。 我尝试在内核模块中执行此操作......并杀死了机器。

顺便说一句 - 我使用的是内核 2.6.18-92.el5,它在内核中链接了 MSR

$ grep -i msr /boot/config-$(uname -r)
CONFIG_X86_MSR=y
...

【问题讨论】:

这会很痛苦,而且会把你的表现送入地狱(好吧,你的应用可能会进行显式预取——但是机器上的任何东西else,像内核一样?)。请注意,关于在预取技术之间进行选择的文章只提到了 P4;较新的芯片与 NetBurst 非常不同!这让我想知道您是否确定必须这样做,或者您是否只是在摸索其他事情。 我的实际目标是通过比较有无预取的总线带宽使用情况(BUS_TRAN_BURST.SELF 事件)来确定有用的 prefecting 数量。 对不起我的无知(从未在内核级别做过任何事情)但我的印象是禁用预取是一件坏事(tm),即它的存在是有原因的,所以不要'别惹它.... .globl _start .text _start: pusha mov msr_pf,%ecx // OF 32 rdmsr mov %edx, hi mov %eax, lo popa mov $1,%eax ; // 终止进程 mov $0,%ebx ; // 结果状态 int $0x80 ; // 系统调用 .data .align 8, 0xff lo: .word 0 hi: .word 0 msr_pf: .word 0x1A0 将所有内容保存在文件中: rdmsr.s 然后: as rdmsr.s -o rdmsr.o ld rdmsr. o -o rdmsr 如果你可以在 ring 0 中运行它,它会工作得很好。 所以你的前提是预取的额外内存实际上没有用?英特尔详细讨论了这个问题:software.intel.com/en-us/articles/…> 【参考方案1】:

2014 年,英特尔发布了有关使用 0x1a4 msr (1a4 msr) 禁用 Nehalem、Westmere、Sandy Bridge、Ivy Bridge、Haswell、Broadwell(可能还有更新的内核)的硬件预取器的信息。链接被bholanathhere找到:

https://software.intel.com/en-us/articles/disclosure-of-hw-prefetcher-control-on-some-intel-processors 披露某些英特尔处理器上的硬件预取器控制 - Vish Viswanathan(英特尔),2014 年 9 月 24 日

本文公开了 MSR 设置,可用于控制基于以下微架构的英特尔处理器上可用的各种硬件预取器:Nehalem、Westmere、Sandy Bridge、Ivy Bridge、Haswell 和 Broadwell。

上述处理器支持 4 种类型的硬件预取器来预取数据。有 2 个与 L1 数据缓存相关的预取器(也称为 DCUDCU 预取器,DCU IP 预取器)和 2 个与 L2 缓存相关的预取器(L2 硬件预取器,L2 相邻缓存行预取器) .

每个内核上都有一个型号特定寄存器 (MSR),地址为 0x1A4,可用于控制这 4 个预取器。该寄存器中的位 0-3 可用于启用或禁用这些预取器。此 MSR 的其他位被保留。

它们对于每个 CPU 内核都是本地的,并且可以在 msr linux 内核驱动程序的帮助下由 root 更改。英特尔使用它们通过英特尔 MLC 工具测量 NUMA 中的内存延迟:

例如,英特尔 Memory Latency Checker 工具 (http://www.intel.com/software/mlc) 通过写入 MSR 0x1a4 来修改预取器以测量准确的延迟并在退出时将其恢复到原始状态。

【讨论】:

作为记录,我已经确认这在 Skylake 上有效。【参考方案2】:

我在这里添加一个答案,因为之前的答案可能不适用于所有英特尔处理器。

对于我的 Intel Xeon 5650(06_2CH 系列)处理器,manual chapter 35 指定地址 0x1A0 处的寄存器 IA32_MISC_ENABLE 的位 10 到 8 被保留。我想这意味着我无法通过 MSR 打开和关闭预取器。

根据英特尔员工here 的回答:“英特尔尚未披露如何在 Nehalem 之后的处理器上禁用预取器。您需要使用 Bios 中的选项来禁用预取器。”

【讨论】:

阅读该帖子后,我看到链接到此新文档的一个 cmets 可能适用(使用不同的 MSR 地址)-software.intel.com/en-us/articles/…【参考方案3】:

您可以使用 msr-tools 启用或禁用硬件预取器 http://www.kernel.org/pub/linux/utils/cpu/msr-tools/。

以下启用硬件预取器(通过取消设置第 9 位):

[root@... msr-tools-1.2]# ./wrmsr -p 0 0x1a0 0x60628e2089 
[root@... msr-tools-1.2]# ./rdmsr 0x1a0 
60628e2089

以下禁用硬件预取器(通过启用第 9 位):

[root@... msr-tools-1.2]# ./wrmsr -p 0 0x1a0 0x60628e2289 
[root@... msr-tools-1.2]# ./rdmsr 0x1a0 
60628e2289

以编程方式,您可以通过打开 /dev/cpu/<cpunumber>/msr 并以 root 身份执行此操作 使用 pwrite 在 0x1a0 偏移处写入 msr“文件”。

【讨论】:

谢谢卡洛斯!之前可能需要执行“modprobe msr”。 我收到了wrmsr: pwrite: Operation not permitted。你知道如何解决它吗?【参考方案4】:

来自英特尔参考: 该指令必须在特权级 0 或实地址模式下执行;否则,将生成一般保护异常#GP(0)。在 ECX 中指定保留或未实现的 MSR 地址也会导致一般保护异常。 ... 应使用 CPUID 指令来确定是否支持 MSR (EDX[5]=1) 在使用此说明之前。 因此,您的故障可能与不支持 MSR 的 CPU 或使用错误的 MSR 地址有关。 在内核源码中有很多使用 MSR 的例子: 在内核源代码中,对于单个 cpu,它在函数中演示了在 arch/i386/kernel/cpu/intel.c 中禁用 Xeon 的预取: static void __cpuinit Intel_errata_workarounds(struct cpuinfo_x86 *c) rdmsr 函数参数是 msr 编号、指向低 32 位字的指针和指向高 32 位字的指针。 wrmsr 函数参数是 msr 编号、低 32 位字值和高 32 位字值。 多核或 smp 系统必须将 cpu 结构作为第一个参数传入: void rdmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 *l, u32 *h); void wrmsr_on_cpu(unsigned int cpu, u32 msr_no, u32 l, u32 h);

【讨论】:

看来我的内核(2.6.18-92.el5)在msr.h中没有rdmsr_on_cpu或wrmsr_on_cpu。这是在 2.6.19 中添加的吗? 在 Debian 选择 2.6.18 之后,根据 lkml.org 于 2007 年 1 月推出补丁:lkml.org/lkml/2007/1/18/91

以上是关于如何以编程方式禁用硬件预取?的主要内容,如果未能解决你的问题,请参考以下文章

iOS 模拟器 - 以编程方式禁用连接硬件键盘

如何以编程方式关闭/禁用 NFC?

如何在 iOS 中以编程方式禁用/启用睡眠模式?

如何以编程方式禁用 Apple Watch 的睡眠模式

如何以编程方式禁用/启用UIBarButtonItem

如何在 Swift 中以编程方式启用/禁用菜单对象