x86 Windows/Linux 应用程序在最小化页数方面是否有性能提升?
Is there a performance gain on x86 Windows/Linux apps in minimizing page count?
我在过去五年的 Windows 和 Linux 上编写和 运行 软件,比如说,在过去五年的机器上。
我相信 运行ning 进程永远不会接近我们拥有的内存量(我们通常使用 32GB 中的 3GB)但我确信我们会填满缓存溢出。
我对数据结构进行了修改,这使得数据结构 运行 变慢了一点(也就是说,做了更多的指针数学运算)但同时减少了缓存行数和页数(工作集)应用程序。
我的理解是,如果进程的内存被分页到磁盘,减少页数并因此减少磁盘 I/O 在挂钟时间和延迟方面是一个巨大的胜利(例如响应网络事件、用户事件、计时器等)但是现在内存如此便宜,我认为使用我的数据结构的进程永远不会内存不足。那么改进这个还有优势吗?例如,如果我使用 10,000 个缓存行,它们分布在 157 个 4k 页面(=643k)还是 10,000 个 4k 页面(=40MB)上有关系吗? 子问题: 即使您离填满 RAM 还差得很远,现代 OS 是否会分页 运行ning 进程? (例如,我认为 90 年代的 Linux 可能这样做是为了增加文件缓存。)
相比之下,我还可以减少缓存行,我怀疑这可能会占用相当多的挂钟时间。为了弄清楚我在计算什么,我正在计算我接触到的至少一个字节的 64 字节对齐内存区域的数量,作为此结构使用的总高速缓存行。示例:如果假设我有 40,000 个 16 字节结构,那么如果这些结构被打包到 10,000 个 64 字节缓存行而不是每个跨越80,000 个缓存行各有两个缓存行?
一般建议是在给定应用程序生命周期的相同时间间隔内,尽量减少在同一内核上表现出高时间局部性的缓存行和虚拟页面的数量。
当所需物理页面的总数即将超过主内存的容量时,OS 将尝试通过将一些驻留页面调出到辅助存储来释放一些物理内存。这种情况可能会导致严重的页面错误,从而显着影响性能。即使您确定系统不会达到那个点,也可能会在不必要地使用更多虚拟页面时出现其他性能问题(即在已使用的页面中浪费 space)。
在 Intel 和 AMD 处理器上,页面 table 条目和其他分页结构缓存在内存管理单元的硬件缓存中,以有效地将虚拟地址转换为物理地址。其中包括 L1 和 L2 TLB。在 L2 TLB 未命中时,称为页面遍历器的硬件组件将参与执行所需的地址转换。更多页面意味着更多未命中。在 pre-Broadwell1 和 pre-Zen 微架构上,任何时候都只能有一个未完成的页面浏览。在后来的微体系结构中,只能有两个。此外,在 Intel Ivy Bridge 及更高版本上,TLB 预取器可能更难跟上未命中数。
在 Intel 和 AMD 处理器上,L1D 和 L2 缓存的设计确保同一 4K 页面内的所有缓存行都映射到不同的缓存集。因此,如果一个页面的所有缓存行都被使用,例如,在 10 个不同页面中展开缓存行,这些缓存级别中的冲突未命中可能会减少。也就是说,在所有 AMD 处理器和英特尔 pre-Haswell 微体系结构上,当访问更多地分布在高速缓存集中时,更可能发生存储体冲突。
在 Intel 和 AMD 处理器上,硬件数据预取器无法跨 4K 边界工作。一种访问模式可以被一个或多个预取器检测到,但访问分布在许多页面上,从硬件预取中获益较少。
在 Windows/Intel 上,工作集管理器每秒重置所有当前页面的页面 table 条目的访问位。因此,当访问不必要地分散在虚拟地址中时 space,每次内存访问需要微代码协助(设置访问位)的页面遍历次数可能会变大。
这同样适用于次要页面错误(在 Intel 和 AMD 上)。 Windows 和 Linux 都使用按需分页,即分配的虚拟页面仅按需映射到物理页面。当访问尚未映射到物理页面的虚拟页面时,会发生次要页面错误。就像访问位一样,每次访问的次要页面错误数量可能更大。
在 Intel 处理器上,访问的页面越多,在同一逻辑核心上附近访问 4K 别名的可能性就越大。有关 4K 混叠的更多信息,请参阅:L1 memory bandwidth: 50% drop in efficiency using addresses which differ by 4096+64 bytes.
可能还有其他潜在问题。
Subquestion: even if you're nowhere near filling up RAM, are there
cases a modern OS will page a running process out anyways? (I think
Linux of the 90s might have done so to increase file caching, for
instance.)
在 Windows 和 Linux 上,每个进程都有最大工作集大小限制。在 Linux 上,这称为 RLIMIT_RSS
并且未强制执行。在 Windows 上,此限制可以是软的(默认)或硬的。该限制仅在困难时才强制执行(可以通过调用 SetProcessWorkingSetSizeEx
函数并传递 QUOTA_LIMITS_HARDWS_MIN_ENABLE
标志来指定)。当进程达到其硬工作集限制时,即使有可用的可用物理内存,也可以通过将其某些页面分页到页面文件来满足进一步的内存分配请求。
我不知道 90 年代的 Linux。
脚注:
(1) Intel 优化手册在第 2.2.3 节中提到,与 Haswell 和更早的微体系结构中的页面相比,Skylake 可以并行执行两个页面遍历。据我所知,该手册没有明确提及 Broadwell 是否可以并行执行一页或两页的步行。但是,根据 these Intel 幻灯片的第 10 页(标题为 "Intel Xeon Processor D: The First Xeon processor optimized for dense solutions"),Xeon Broadwell 支持两页浏览。我认为这也适用于所有 Broadwell 型号。
我在过去五年的 Windows 和 Linux 上编写和 运行 软件,比如说,在过去五年的机器上。
我相信 运行ning 进程永远不会接近我们拥有的内存量(我们通常使用 32GB 中的 3GB)但我确信我们会填满缓存溢出。
我对数据结构进行了修改,这使得数据结构 运行 变慢了一点(也就是说,做了更多的指针数学运算)但同时减少了缓存行数和页数(工作集)应用程序。
我的理解是,如果进程的内存被分页到磁盘,减少页数并因此减少磁盘 I/O 在挂钟时间和延迟方面是一个巨大的胜利(例如响应网络事件、用户事件、计时器等)但是现在内存如此便宜,我认为使用我的数据结构的进程永远不会内存不足。那么改进这个还有优势吗?例如,如果我使用 10,000 个缓存行,它们分布在 157 个 4k 页面(=643k)还是 10,000 个 4k 页面(=40MB)上有关系吗? 子问题: 即使您离填满 RAM 还差得很远,现代 OS 是否会分页 运行ning 进程? (例如,我认为 90 年代的 Linux 可能这样做是为了增加文件缓存。)
相比之下,我还可以减少缓存行,我怀疑这可能会占用相当多的挂钟时间。为了弄清楚我在计算什么,我正在计算我接触到的至少一个字节的 64 字节对齐内存区域的数量,作为此结构使用的总高速缓存行。示例:如果假设我有 40,000 个 16 字节结构,那么如果这些结构被打包到 10,000 个 64 字节缓存行而不是每个跨越80,000 个缓存行各有两个缓存行?
一般建议是在给定应用程序生命周期的相同时间间隔内,尽量减少在同一内核上表现出高时间局部性的缓存行和虚拟页面的数量。
当所需物理页面的总数即将超过主内存的容量时,OS 将尝试通过将一些驻留页面调出到辅助存储来释放一些物理内存。这种情况可能会导致严重的页面错误,从而显着影响性能。即使您确定系统不会达到那个点,也可能会在不必要地使用更多虚拟页面时出现其他性能问题(即在已使用的页面中浪费 space)。
在 Intel 和 AMD 处理器上,页面 table 条目和其他分页结构缓存在内存管理单元的硬件缓存中,以有效地将虚拟地址转换为物理地址。其中包括 L1 和 L2 TLB。在 L2 TLB 未命中时,称为页面遍历器的硬件组件将参与执行所需的地址转换。更多页面意味着更多未命中。在 pre-Broadwell1 和 pre-Zen 微架构上,任何时候都只能有一个未完成的页面浏览。在后来的微体系结构中,只能有两个。此外,在 Intel Ivy Bridge 及更高版本上,TLB 预取器可能更难跟上未命中数。
在 Intel 和 AMD 处理器上,L1D 和 L2 缓存的设计确保同一 4K 页面内的所有缓存行都映射到不同的缓存集。因此,如果一个页面的所有缓存行都被使用,例如,在 10 个不同页面中展开缓存行,这些缓存级别中的冲突未命中可能会减少。也就是说,在所有 AMD 处理器和英特尔 pre-Haswell 微体系结构上,当访问更多地分布在高速缓存集中时,更可能发生存储体冲突。
在 Intel 和 AMD 处理器上,硬件数据预取器无法跨 4K 边界工作。一种访问模式可以被一个或多个预取器检测到,但访问分布在许多页面上,从硬件预取中获益较少。
在 Windows/Intel 上,工作集管理器每秒重置所有当前页面的页面 table 条目的访问位。因此,当访问不必要地分散在虚拟地址中时 space,每次内存访问需要微代码协助(设置访问位)的页面遍历次数可能会变大。
这同样适用于次要页面错误(在 Intel 和 AMD 上)。 Windows 和 Linux 都使用按需分页,即分配的虚拟页面仅按需映射到物理页面。当访问尚未映射到物理页面的虚拟页面时,会发生次要页面错误。就像访问位一样,每次访问的次要页面错误数量可能更大。
在 Intel 处理器上,访问的页面越多,在同一逻辑核心上附近访问 4K 别名的可能性就越大。有关 4K 混叠的更多信息,请参阅:L1 memory bandwidth: 50% drop in efficiency using addresses which differ by 4096+64 bytes.
可能还有其他潜在问题。
Subquestion: even if you're nowhere near filling up RAM, are there cases a modern OS will page a running process out anyways? (I think Linux of the 90s might have done so to increase file caching, for instance.)
在 Windows 和 Linux 上,每个进程都有最大工作集大小限制。在 Linux 上,这称为 RLIMIT_RSS
并且未强制执行。在 Windows 上,此限制可以是软的(默认)或硬的。该限制仅在困难时才强制执行(可以通过调用 SetProcessWorkingSetSizeEx
函数并传递 QUOTA_LIMITS_HARDWS_MIN_ENABLE
标志来指定)。当进程达到其硬工作集限制时,即使有可用的可用物理内存,也可以通过将其某些页面分页到页面文件来满足进一步的内存分配请求。
我不知道 90 年代的 Linux。
脚注:
(1) Intel 优化手册在第 2.2.3 节中提到,与 Haswell 和更早的微体系结构中的页面相比,Skylake 可以并行执行两个页面遍历。据我所知,该手册没有明确提及 Broadwell 是否可以并行执行一页或两页的步行。但是,根据 these Intel 幻灯片的第 10 页(标题为 "Intel Xeon Processor D: The First Xeon processor optimized for dense solutions"),Xeon Broadwell 支持两页浏览。我认为这也适用于所有 Broadwell 型号。