webassembly007 OPTIMIZING CACHE USAGE && CPU Cache Optimization

参考

CPU的cache

        CPU的cache是一种高速存储器,位于CPU内部,用于临时存储频繁使用的数据和指令。它的存在主要是为了解决CPU与主存之间的速度差异,提高计算机的性能。

CPU的缓存工作原理如下:

  1. 缓存命中与缓存失效:当CPU需要访问某个内存地址时,它首先检查该地址是否在缓存中。如果在缓存中找到了该地址对应的数据,则称为缓存命中,CPU可以直接从缓存中读取数据,这样可以大大提高访问速度。如果地址不在缓存中,则称为缓存失效,CPU需要从主存中读取数据,并将其加载到缓存中。

  2. 局部性原理:CPU缓存利用了程序的局部性原理,即程序在一段时间内倾向于访问相同或附近的内存地址。这是由于程序的指令和数据通常以连续的方式存储在主存中。

  3. 缓存层次结构:CPU的缓存通常分为多级缓存,如L1、L2和L3缓存。这些缓存按照容量和访问速度递减的顺序排列,L1缓存最小但最快,L3缓存最大但最慢。CPU在访问内存时,首先查找L1缓存,如果数据不在L1缓存中,则继续查找L2缓存,以此类推。

  4. 缓存行:CPU的缓存以缓存行的方式组织数据。缓存行是内存中一块连续的数据块,通常大小为64字节(B)或128字节(B)当CPU需要访问内存中的某个地址时,它会将该地址所在的缓存行加载到缓存中,以便快速访问。

  5. 缓存替换策略:当缓存已满,且需要将新的数据加载到缓存中时,需要选择一个缓存行来替换。常见的缓存替换策略有最近最少使用(LRU)、最不经常使用(LFU)和随机替换等。

图解说明

在这里插入图片描述

L1、L2和L3缓存之间的性能差异

access latencyCPU周期时间(单位ns)
寄存器1 cycle
L1 Cache~3-4 cycles~0.5-1 ns
L2 Cache~10-20 cycles~3-7 ns
L3 Cache~40-45 cycles~15 ns
内存~120-240 cycles~60-120ns

cache和内存的映射

直接相联方式 : 主存储器中一块只能映象到Cache的一个特定的块中。

  • 地址变换过程:用主存地址中的块号B去访问目录存储器, 把读出来的区号与主存地址中的区号E进行比较, 比较结果相等,有效位为1,则Cache命中,可以直接用块号及块内地址组成的缓冲地址到缓存中取数;比较结果不相等,有效位为1, 可以进行替换,如果有效位为0,可以直接调入所需块。
    在这里插入图片描述

  • 例:32位计算机,cache容量16kb( 2 14 2^{14} 214b,cache地址有14位),主存0x12345678装入地址,将0x12345678转为二进制选择后14位即可。

全相联方式:主存的任意一块可以映象到Cache中的任意一块

在这里插入图片描述
在这里插入图片描述

组相联映象方式

(1) 主存和Cache按同样大小划分成块。

(2) 主存和Cache按同样大小划分成组。

(3) 主存容量是缓存容量的整数倍,将主存空间按缓冲区的大小分成区,主存中每一区的组数与缓存的组数相同。

(4) 当主存的数据调入缓存时,主存与缓存的组号应相等,也就是各区中的某一块只能存入缓存的同组号的空间内,但组内各块地址之间则可以任意存放, 即从主存的组到Cache的组之间采用直接映象方式;在两个对应的组内部采用全相联映象方式。

块的替换规则

        直接相联不需要替换策略,因为其本身的映射方式已经决定了一个主存块应该放进哪个 Cache Line。而组相联和全相联是需要替换策略的,常见的替换策略如下:

  • 随机替换
  • 先进先出
  • 最近最少使用(LRU)

块写策略

cache写命中

写缺失策略

缓存命中率是指在访问缓存中的数据时,所请求的数据是否能够在缓存中找到的比率。它是衡量缓存性能的重要指标之一。

提高缓存命中率的软件优化方法如下:

  1. 提高局部性:局部性是指程序在一段时间内对某些数据的访问集中在一定的地址范围内。通过优化算法和数据结构,可以提高程序的局部性,从而增加缓存命中率。

  2. 数据预取:通过预测程序的访问模式,提前将可能被访问的数据加载到缓存中,减少缓存未命中的情况。

  3. 数据对齐:将数据按照缓存行的大小进行对齐,可以减少缓存未命中的情况。

  4. 减少冲突:冲突是指多个数据映射到同一个缓存位置,导致缓存未命中。通过增加缓存的大小、优化缓存的映射方式等方法,可以减少冲突,提高缓存命中率。

  5. 缓存替换算法:选择合适的缓存替换算法,可以在缓存未命中时选择最有可能被访问的数据替换出来,提高缓存命中率。

  6. 数据压缩:通过压缩数据,可以减少数据在缓存中的占用空间,增加缓存的容量,从而提高缓存命中率。

  7. 减少伪共享(false sharing) https://www.codeproject.com/Articles/85356/Avoiding-and-Identifying-False-Sharing-Among-Threa
    在这里插入图片描述

  8. 非时态数据

examples

  • https://studylib.net/doc/18141740/cpu-cache-optimization–does-it-matter
cache利用率

在这里插入图片描述在这里插入图片描述在这里插入图片描述

数据对齐(int 4 byte ,char 1 byte)

在这里插入图片描述在这里插入图片描述在这里插入图片描述

按照行访问

在这里插入图片描述在这里插入图片描述

falseSharing
  • https://github.com/MJjainam/falseSharing
  • false sharing(伪共享) 及 c代码实现
  • Int array[100]数组,线程1对0号位置的元素修改,实现累加100M次,线程2对1号位置的元素修改,实现累加100M次,由于两个线程修改的数据共享同一cache line,所以造成false sharing;如何改进呢?将线程2对16号位置的元素做修改,因为一行cache line占64字节,相当于16个int类型元素,所以进行padding,达到两个线程用两个cache line的目的,即可消除问题。
  • Struct test{}结构体,里面包含int num_int,long num_long,int arr[16] 三种数据类型,这三种数据类型的位置摆放也影响了性能,如果按照这个顺序排列,实现对 num_int和num_long数据类型的累加操作并修改,一个线程写num_int,另一个写num_long,由于在同一cache line,存在false sharing,而我们把arr数组放到 num_long前面,将要修改的两个数据放到不同的cache line中,即可消除问题,因为arr数组占据了16个字节,跨越到下一个cache line了
  • 感觉和GPU的bank冲突有些类似

CG

simd

        在过去的十年里,处理器的速度一直在提高。内存访问速度以较慢的速度增加。由此产生的差异使得以两种方式之一调整应用程序变得很重要:(a)大多数数据访问都是从处理器缓存中完成的,或者(b)有效地屏蔽内存延迟,以尽可能多地利用峰值内存带宽。
        硬件预取机制是微体系结构中的增强功能,有助于实现后一个方面,当与软件调优相结合时,它将是最有效的。如果所需的数据可以从处理器缓存中提取,或者如果内存流量可以有效地利用硬件预取,那么大多数应用程序的性能都可以得到显著提高。
        在需要数据之前将数据带入处理器的标准技术涉及额外的编程,这可能很难实现,并且可能需要特殊步骤来防止性能下降。
“数据流单指令多数据扩展指令集”(Streaming SIMD Extensions)通过提供各种预取指令来解决这个问题。SIMD引入了各种非临时存储指令。SSE2扩展了这一点支持新的数据类型,还引入了对32位整数寄存器的非临时存储支持。

        本章重点介绍:

  • 硬件预取机制、软件预取和可缓存性说明–讨论允许您影响应用程序中数据缓存的微体系结构功能和说明。
  • 使用硬件预取、软件预取和可缓存性指令的内存优化–讨论使用上述指令实现内存优化的技术。
  • 使用确定性缓存参数来管理缓存层次结构。
#include <time.h>
struct timespec before, after;
long elapsed_nsecs;

int main(){

//    struct DATB
//    {
//        int a;
//        int b;
//    };
//    DATB pMyDatb[10*1024];
//    clock_gettime(CLOCK_REALTIME, &before);
//    for(int j=0;j<100000;j++)
//    for (long i=0; i<10*1024; i++) {
//        pMyDatb[i].a = pMyDatb[i].b;
//    }
//    clock_gettime(CLOCK_REALTIME, &after);
//    elapsed_nsecs = (after.tv_sec - before.tv_sec) * 1000000000 +(after.tv_nsec - before.tv_nsec);
//    printf("elapsed : %ld",elapsed_nsecs);//1597293426

    struct DATA
    {
        int a;
        int b;
        int c;
        int d;
    };
    DATA pMyData[10*1024];
    long elapsed_nsecs;

    clock_gettime(CLOCK_REALTIME, &before);
    for(int j=0;j<100000;j++)
    for (long i=0; i<10*1024; i++) {
        pMyData[i].a = pMyData[i].b;
    }
    clock_gettime(CLOCK_REALTIME, &after);

    elapsed_nsecs = (after.tv_sec - before.tv_sec) * 1000000000 +
                    (after.tv_nsec - before.tv_nsec);
    printf("elapsed : %ld",elapsed_nsecs);// elapsed : 1620390389
    
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值