惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
IT之家
IT之家
Cyberwarzone
Cyberwarzone
T
Troy Hunt's Blog
有赞技术团队
有赞技术团队
阮一峰的网络日志
阮一峰的网络日志
T
Threat Research - Cisco Blogs
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
G
GRAHAM CLULEY
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
博客园 - 叶小钗
Last Week in AI
Last Week in AI
C
CERT Recently Published Vulnerability Notes
The Hacker News
The Hacker News
Jina AI
Jina AI
T
Tor Project blog
V
Vulnerabilities – Threatpost
酷 壳 – CoolShell
酷 壳 – CoolShell
Spread Privacy
Spread Privacy
博客园_首页
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Simon Willison's Weblog
Simon Willison's Weblog
Security Latest
Security Latest
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 司徒正美
V2EX - 技术
V2EX - 技术
I
Intezer
The Cloudflare Blog
Cisco Talos Blog
Cisco Talos Blog
SecWiki News
SecWiki News
博客园 - 【当耐特】
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
L
Lohrmann on Cybersecurity
Scott Helme
Scott Helme
Google Online Security Blog
Google Online Security Blog
量子位
The Last Watchdog
The Last Watchdog
AI
AI
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Security Affairs
P
Palo Alto Networks Blog
S
Secure Thoughts
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Attack and Defense Labs
Attack and Defense Labs

博客园 - 叫我安不理

C#如何优雅处理引用类型的深拷贝 老马失前蹄,竟然在数据库外键上翻车了,重温外键级联 字符编码知多少(二) 字符编码知多少(一) 给自己看的mongoDB快速入门 为什么OAuth2与SSO经常混为一谈? 优雅求模,一致性哈希算法 浅谈为什么我讨厌分布式事务 为什么说方法的参数最好不要超过4个? 浅谈.NET微服务架构的演变 C#网络编程(六)----Socket编程模型 C#网络编程(五)----细嗦TCP粘包 C#网络编程(四)----HttpClient C#网络编程(三)----HTTP协议 C#网络编程(二)----网络层/链路层 C#网络编程(一)----应用层/传输层 重生之我是操作系统(十)----I/O管理 重生之我是操作系统(九)----文件管理(下) 重生之我是操作系统(八)----文件管理(上) 重生之我是操作系统(七)----内存管理(下)
C#代码如何影响CPU缓存速度?
叫我安不理 · 2025-06-07 · via 博客园 - 叫我安不理

CPU与RAM的隔阂

CPU与RAM是两个独立的硬件,并非集成在一起。所以他们两个之间一定会存在一个连接的桥梁,这个桥梁的名字叫做内存总线。

内存总线由三部分组成:

  1. 地址总线(Address Bus)
    用于传输内存地址,也就是我们经常看到的0X77F84FAB这种类似的内存地址,一根总线代表一个电信号,一个电信号能传递高电平/低电平两种信息,用二进制表示就是1/0。因此总线数量的多少决定了可以传递内存地址的大小,比如你有32根总线,就代表你总线宽度32。2^32=4294967296,等于4GB内存,这就是32位操作系统只支持4G内存的由来。

  2. 数据总线(Data Bus)
    用于传输数据,原理同上,一根总线代表1bit传输段位,64根总线就是 64bit=8byte。一次性可以传输8byte单位的数据。

  3. 控制总线(Control Bus)
    用户传输控制信号,比如一根用来"读信号输出"的开关,一根"写信号输出"的开关。一根"时钟信号"的开关

更详细可以参考此文:https://www.cnblogs.com/lmy5215006/p/18469027

CPU Cache

可以看到,假设CPU要读取1kb的数据,你的数据总线总线只有64根,1024/8=128,你需要来回倒腾128次,才能读取完毕,这一来二去就加大了内存之间的延迟,为了优化此性能瓶颈,
CPU除了寄存器外临时存储数据,还内置了Cache来临时存储数据与指令。

游戏神U 9800x3d就是依靠96MB的"巨大L3缓存",来降低了内存延迟,从而在游戏场景默秒全Intel

特性 L1缓存 L2缓存 L3缓存
速度 1-2纳秒 约10纳秒 约30纳秒
容量 几十KB到几百KB 几百KB到几MB 几MB到几十MB
位置 集成在 CPU 核心内部 每个核心独立拥有(位于核心附近) 多核共享(位于 CPU 芯片内)
缓存一致性 每个核心独立,与L3主从同步 每个核心独立,与L1/L3主从同步 多核共享
场景 需要立即执行的指令与高频访问的数据 稍低频但重复访问的数据 跨核心共享数据、大吞吐量计算

image

what is CacheLine?
CacheLine是CPU缓存中最小数据单元,当CPU从内存中读取数据时,会一次性加载64byte的数据,而不是只加载特定数据,即使只想读取1bit数据,也会加载64byte数据。这么做是因为,大多数情况下,数据都是顺序读取的,因此提前加载数据有利于减少延迟。

眼见为实

使用Coreinfo 来观察CPU

image

C#代码如何影响CPU缓存速度?

internal class Program
{
    static void Main(string[] args)
    {
        Stopwatch sw = new Stopwatch();

        sw.Start();
        Rows();
        sw.Stop();
        Console.WriteLine($"逐行赋值执行时间:{sw.ElapsedMilliseconds}");

        sw.Restart();
        Columns();
        sw.Stop();
        Console.WriteLine($"逐列赋值执行时间:{sw.ElapsedMilliseconds}");
    }

    static void Rows()
    {
        int[,] tab = new int[5000, 5000];

        for (int i = 0; i < 5000; i++)
        {
            for (int j = 0; j < 5000; j++)
            {
                tab[i, j] = 1;//逐行赋值,能成功利用到Cacheline提前加载的数据
            }
        }
    }

    static void Columns()
    {
        {
            int[,] tab = new int[5000, 5000];

            for (int i = 0; i < 5000; i++)
            {
                for (int j = 0; j < 5000; j++)
                {
                    tab[j, i] = 1;//逐列赋值,无法利用Cacheline提前加载的数据,只能丢弃重新读取。
                }
            }
        }
    }
}

image

可以看到,非线性的数据检索带来了严重的性能问题,应当尽量避免对内存的非顺序访问。