c++内存序和内存屏障
内存序是为了指令有序(因为编译器、cpu会对指令顺序进行优化,提高内存和寄存器利用率)
内存屏障依赖底层硬件系统,当到达内存屏障的时候,内存相关写代码要全部完成,保证数据不是脏读。
零拷贝(有篇博客园的帖子写的很好)
b和b+树
红黑树
前端渲染效率和图像渲染里面的渲染效率是一个吗?
或者说锁、原子性具体是为了解决什么问题,比如并发下的数据竞争?
锁和原子性都是为了在多线程或者进程访问共享内存数据的时候,发生数据竞争,导致读到的数据不对。
cpu在读取数据的时候,最终是加载到内存里还是缓存?
这篇文章写的很好:https://www.cnblogs.com/beilou310/p/18109156
CPU 的核心操作单元(如 ALU - 算术逻辑单元)是“盲”的:
ALU 是执行加、减、乘、除、与、或、非等实际运算的硬件电路。
ALU 的设计使其只能直接访问寄存器。 它对内存地址一无所知。当你写一条指令如 add eax, ebx 时,ALU 知道的是“把寄存器 eax 和 ebx 里的值拿来,相加,然后把结果存回 eax”。它无法直接去内存地址 0x12345678 取值来加。
指令集架构(ISA)的规定:
处理器支持的指令(指令集)在语法上明确规定了操作数的来源和目标。
绝大多数直接作用于数据的指令(如算术、逻辑、移位指令)的操作数必须是寄存器。 例如在 x86 架构中:
add rax, rbx -> 两个操作数都是寄存器。
add rax, [mem_address] -> 看起来像是内存操作数,但这条指令在执行时 ,CPU 会先 将 mem_address 处的数据加载到一个临时寄存器 (这个过程对程序员透明),然后再执行 add rax, temp_reg。内存操作数在硬件层面最终还是变成了寄存器操作数。
少数指令(如 mov)可以在寄存器和内存之间传输数据,但它们本身不执行计算。
寄存器是CPU最快的存储单元:
寄存器是位于CPU核心内部的微小、高速的存储单元,访问延迟通常只需要1个时钟周期 。
缓存(L1, L2, L3)虽然也很快(L1缓存访问通常需要3-5个周期),但它们在物理上位于CPU核心之外(尤其是L2/L3),访问速度仍然显著慢于寄存器。
内存的访问速度(通常需要几十到几百个周期)相比寄存器更是慢了几个数量级。
为了最大化CPU的执行速度,让ALU只与距离最近、速度最快的寄存器交互是最优设计。
数据流动的过程(简化):
CPU 需要数据: CPU 执行到一条需要数据的指令(例如 add eax, DWORD PTR [0x1000])。
检查缓存:
CPU 首先检查最快的 L1 缓存,看看地址 0x1000 的数据是否在缓存中。
如果在(缓存命中),则直接从 L1 缓存读取数据。如果不在(缓存未命中)...
检查 L2 缓存 -> 如果命中则读取。如果未命中...
检查 L3 缓存(如果有)-> 如果命中则读取。如果仍然未命中...
访问主存(慢): 最终需要去主内存 (RAM) 中读取地址 0x1000 处的数据。这个过程很慢。
填充缓存(可选): 从内存读取数据后,通常会同时将该数据及其附近的数据加载到 L3/L2/L1 缓存中(按缓存策略),以便后续访问更快。
加载到寄存器: 无论数据最终是从 L1, L2, L3 缓存还是主内存中获取的,CPU 在完成步骤 1-4 后,下一步一定是将该数据从它所在的缓存层级(或内存控制器缓冲区)拷贝到目标寄存器(比如一个临时寄存器,或者指令中指定的寄存器如 eax)。
执行运算: 现在,数据已经位于寄存器中了。CPU 控制单元将寄存器中的数据送入 ALU 执行加法操作。结果通常也写回到寄存器中。
写回(如果需要): 如果运算结果需要写回内存,CPU 会将结果从寄存器拷贝到缓存(通常在 L1),再由缓存控制器在适当的时候将数据写回主内存。
浙公网安备 33010602011771号