【高性能计算】内存结构与优化理论

cachemiss

  • 现代操作系统采用虚拟内存的管理机制,系统在访问某一内存页时需要首先利用页表机制将虚拟地址映射到物理地址,如果在查找的过程中发现页表中没有对应的映射条目,就会发成缺页异常
  • 页表通常存储在物理内存中,类似于缓存机制,常用的页表项会被加载到 TLB (Translation Look-aside Buffer)中以加快页表的访问。内存映射单元(MMU)会优先访问 TLB 获取物理地址映射,但是如果 TLB 不命中将导致 MMU 需要从内存中加载页表项,因此 TLB 不命中势必会影响程序的执行效率
  • 利用 malloc 和 free 等函数在堆空间中申请和释放动态内存
  • 缺页处理程序:如果此时页表项存在磁盘地址,则需要分配一个物理页并将内容从磁盘重新拷贝进物理内存,建立起映射关系(此时成为major fault,耗时较高);如果页表项为空,则直接分配物理页并建立映射关系(此时成为 minor fault)
  • 虚拟内存管理中,每一个进程都有一个独立的虚拟内存空间,每一个进程的页表项都常驻内存。
  • MMU 是处理器中集成的一个专门用于地址管理的硬件。

cacheline

  • CPU 上的 cacheline 大小是 64B、(NVIDIA) GPU 上是128 B,内存带宽的瓶颈往往是 last-level
    cache (LLC,比如 CPU 上的 L3 cache、GPU 上的 L2 cache) 到 main memory(也就是内存条)的 bandwidth
  • cache分成多个组,每个组分成多个行,linesize是cache的基本单位,从主存向cache迁移数据都是按照linesize为单位替换的
  • Cache总大小为32KB,8路组相连(每组有8个line),每个line的大小linesize为64Byte,可以很轻易的算出一共有32K/8/64=64 个组

数据结构方式

struct AoSData
{
    public int a;  //a[1] AoSData[100]
    public int b;
    public int c;
    public int d;
}

struct SoAData
{
    public NativeArray<int> aArray;  // aArray[100] SoAData[1]
    public NativeArray<int> bArray;
    public NativeArray<int> cArray;
    public NativeArray<int> dArray;
}

在这里插入图片描述

  • 如果你的访问是顺序访问,那么 SOA 通常比 AOS 效率高一些。特别是当你的程序在 GPU 上运行的时候,因为 Coalescing
  • 如果你的访问是随机访问,那么 AOS 常常比 SOA 更好。因为随机访问的一个粒子的数据在 AOS 下是在同一个 cacheline 中,而在 SOA 布局下会分散在 N 个 cachelines 里面,对于 AOS 的 cacheline utilization(缓存行利用率)会高很多。

内存对齐与分配释放

  • 因为随意分配的地址可能addr % p != 0 (p等于8 / 16 / 等等), 所以我们一般的做法是先分配一个比申请空间稍大的空间, 然后将这个头地址, 往前移动几个字节, 使得新的addr满足 % p = 0
  • 空间申请,代码如下:
 unsigned char* udata = (unsigned char*)malloc(size + sizeof(void*) + MALLOC_ALIGN);
 // sizeof(void*) 等于8字节, 
  • 我们明明只申请了size字节大小的空间, 为啥要多分配sizeof(void*)+ MALLOC_ALIGN这么多的空间呢? 理由是为了保存原始地址 + 对齐
  • 关于NCNN中内存申请与对齐,见此文章
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值