• 多线程


    CPU性能优化 - 缓存

    为了提高程序运行的性能,现代CPU在很多方面会对程序进行优化。CPU的处理速度是很快的,内存的速度次之,硬盘速度最慢。在cpu处理内存数据中,内存运行速度太慢,就会拖累cpu的速度。为了解决这样的问题,cpu设计了多级缓存策略。

    CPU分为三级缓存: 每个CPU都有L1,L2 但是L3是多核公用的。

    • L1 Cache (一级缓存)是CPU第一层告诉缓存,分为数据缓存和指令缓存。一般服务器的CPU的L1缓存的容量通常在32-4096K
    • L2 Cache (二级缓存)由于L1高速缓存的容量限制,为了再次提高CPU的运算速度,在CPU外部放置一告诉存储器,即二级缓存。
    • L3 Cache (三级缓存) 都是内置的,它的作用是进一步降低内存延迟,同事提升大数据量计算时处理器的性能。具有较大L3缓存的处理器,能提供更有效的文件系统缓存行为及较短的消息和队列长度。一般多核共享一个L3缓存。

    CPU查找数据的顺序为: CPU -> L1 -> L2 -> L3 -> 内存 -> 硬盘

    缓存同步协议

    因为每个CPU都有自己的缓存,容易导致一种情况就是 如果多个CPU的缓存(多CPU读取同样的数据进行缓存,进行不同运算后,写入内存中)中都有同样一份数据,那这个数据要如何处理呢?已谁的为准? 这个时候就需要一个缓存同步协议了!
    MESI协议 规定每条缓存都有一个状态位,同时定义了一下四种状态:

    • 修改态 (Modified) 此缓存被修改过,内容与住内存不同,为此缓存专有
    • 专有态 (Exclusive) 此缓存与主内存一致,但是其他CPU中没有
    • 共享态 (Shared) 此缓存与住内存一致,但也出现在其他缓存中。
    • 无效态 (Invalid) 此缓存无效,需要从主内存中重新读取。

    多处理器,单个CPU对缓存修改,需要通知其他CPU. 也就意味着,CPU需要控制自己的读写,还需要监听其他CPU发出的通知,从而保持最终一致性。

    CPU性能优化 - 运行时指令重排序

    例如如下代码是:

    指令重排:当CPU 写缓存 时发现缓存区被其他CPU占用,为了提高CPU处理性能,可能将后面的读缓存命令优先执行
    指令重排序,遵循 as-if-serial语义。即指令重排序前后,程序执行的结果不能变化。对于数据有依赖的部分,不会进行重排序。

    问题

    1、CPU高速缓存的问题:
    缓存中的数据与主内存的数据不是实时同步的,各个CPU间缓存的数据也不是实时同步的,在同一时间点,各个CPU所看到的的同一内存地址的数据可能是不一致的

    2、CPU指令重排优化问题:
    虽然遵循 as-if-serial语义,但是它是仅在单个CPU自己执行的情况下保证结果正确,多核多线程,指令逻辑无法分辨因果关联,可能出现乱序执行,导致程序结果出现错误。

    内存屏障解决以上问题

    写内存屏障(Store Memory Barrier):在指令后插入Store Barrier,能让写入缓存中最新数据更新写入主内存中,让其他线程可见。 强制写入主内存,这种显示调用,不会让CPU去进行指令重排序
    读内存屏障(Load Memory Barrier):在指令后插入Load Barrier,可以让高速缓存中的数据失效,强制重新从住内存中加载数据。 也是不会让CPU去进行指令重排。

  • 相关阅读:
    DripRoad(点滴之路)
    如何写优雅的代码
    .Net 一直在改变
    Protobufnet的完美解决方案
    关于msgpack序列化后的消息包是否再压缩
    失眠
    创建一个比微软性能更好空间更少的GUID
    msgpack与protobuf的简单性能测试对比
    分布式游戏服务器的登陆流程
    对象池的实现与性能测试
  • 原文地址:https://www.cnblogs.com/junjiedeng/p/11679596.html
Copyright © 2020-2023  润新知