繁体   English   中英

rdtsc代码显示内存特性(如TLB未命中)对性能的影响

[英]rdtsc code that shows performance impacts from memory characterstics such as TLB miss

我试图了解rdtsc(),并从http://www.mcs.anl.gov/~kazutomo/rdtsc.html遇到了以下代码。解释该代码的文字为“下一个简短的基准代码可能会向您显示内存特性会影响性能,例如TLB未命中,页面错误或页面交换进/出。”问题是,我不太了解内存特性如何显示性能。老实说,我没有任何线索。如果有人可以解释一下这将是很棒的。

#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

#include "rdtsc.h"

#define N (1024*1024*2)

int main(int argc, char* argv[])
{
  unsigned long long a,b;
  unsigned long long min,max;
  char* p;
  int i;

  p = (char*)malloc(N);
  assert( p!=(char*)0 );

  max = 0;
  min = UINT64_MAX;

  for(i=0; i<N; i++ ) {
    a = rdtsc();
    p[i] = 0;
    b = rdtsc() - a;
    if( b > max ) max = b;
    else if( b < min ) min = b;
  }
  printf("min=%llu\n", min);
  printf("max=%llu\n", max);
  return 0;
}

这段代码只是循环通过2MB缓冲区,向其每个字节写入0 ,并计算执行每次写入所花费的时间,更新显示最短和最长时间的高低水位标记( minmax )。进行每次写入所需。

假设该程序是在CPU上运行的唯一程序,并且假设它在运行时没有发生任何异步事件(硬件中断或计时器中断),则该程序将向您显示进行字节宽写入内存的标称时间以及处理TLB丢失异常和/或页面错误异常所需的最长时间。

TLB未命中异常是内核在程序尝试访问MMU中没有TLB条目的内存时采用的异常。 MMU是Core Avenue和Memory Lane交叉路口的警务人员,负责将交通引导至应该去的地方。 好,这是一个可怕的比喻。 MMU(内存管理单元)具有两个主要目的:1)将虚拟内存访问路由到适当的物理内存地址,以及2)强制执行只读,读写,读取执行,仅执行等特权,以便对具有冲突属性的虚拟内存区域(或对未映射的虚拟内存区域)的杂散指针访问将被捕获并引发内存访问异常(例如Linux上的SIGSEGV)。 TLB条目是MMU中的一组硬件寄存器,用于告知MMU虚拟内存页面或当前加载到物理内存中的页面组的权限。 但是,MMU没有无限数量的TLB条目。 它几乎没有足够的TLB条目来描述所有内存页面的属性。 因此,如果您尝试从流程的地址空间访问没有当前TLB条目描述其所在页面的合法地址,则会遇到TLB未命中的情况。 然后,TLB遗漏异常处理程序会从主内存中获取正确的TLB条目数据,并将其写入MMU中的TLB条目中; MMU甚至可能具有一些内置机制,用于告知TLB未命中异常处理程序应使用哪个TLB条目...可能是最近最少使用的条目,这是在不久的将来最可能不再需要的条目。

页面错误类似于TLB未命中异常,不同之处在于在这种情况下,该虚拟内存页面的内容甚至不在物理内存中……它可能根本不存在(新映射的内存页面),或者它可能先前已换出到磁盘上,以便在有限的物理内存中为程序有时需要的另一页虚拟内存腾出空间。 尽管TLB未命中异常通常非常快(但是仍然会影响性能),但是由于必须从磁盘(甚至从SSD!)中拉出页面,因此页面错误异常可能会对性能造成巨大影响。比内存访问慢一个数量级(或更糟!)。 因此,为了让CPU忙于处理有用的事情 ,操作系统的页面错误异常处理程序通常会导致当前正在运行的进程换出以支持运行其他进程(处于“就绪”状态的进程),在磁盘上等待接收数据以填满请求的虚拟内存页面。

现在,回到此“测试代码”及其结果的有效性:

此测试取决于OS + runtime在对malloc(N)的调用中未预分配内存页面。 我相信这可能是典型的行为; 即使运行时分配了这么多的内存并知道其分配的地址范围,但操作系统通常不会分配该内存的实际页面,直到您的程序实际访问(读取或写入)给定页面中的地址为止。 在许多平台上,页面的大小为4KB,但也可能更大,例如,较新的Intel Pentium衍生产品的页面大小为4MB。

因此,假设平台的页面大小为4KB(4096字节),当您的程序遍历2MB分配的空间,一次向其写入0字节时,它将遍历这4KB页面中的1024个。 因此,这些写入中的4193280应该“尽可能快地”发生(不触发TLB丢失或页面错误异常)。 并且其中多达1024个将触发TLB丢失和/或页面错误异常。 因此,鉴于写入的地址位于已加载的虚拟内存页面中并且其TLB条目当前位于MMU中,因此“最小”时间为执行写入提供了最快的时间。 “最大”时间为执行写操作提供了最坏的可能时间,大概是写给尚未映射到物理内存中的页面上的地址(并触发了页面错误异常,也可能触发了TLB未命中异常)。

如果我们依靠其测试结果来揭示底层硬件的某些特性,则此测试有两个问题:1)就其本身而言,此代码忽略了进程交换和/或由于其他原因(例如时间)导致的硬件中断的影响-切片和网络数据包“在后台”被接收和处理(这可能会中断正在运行的进程)。 而且... 2)2MB的测试缓冲区甚至不及新型Intel处理器的MMU的4MB页面大小。 我不知道什么条件决定操作系统选择使用4KB页面还是4MB页面,因此这可能对您的系统造成影响。 请注意,如果您的minmax彼此处于相同的数量级,则可能是您使用的系统具有4MB页面,并且如果您的minmax相差一个数量级或更多,则差异可能不能完全归因于TLB未命中和页面错误异常。 也许这就是为什么作者在声明中对代码“ 可能会向您显示一些性能影响...”稍加掩饰的原因(加了强调)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM