当前位置:网站首页>缓存--伪共享问题
缓存--伪共享问题
2022-08-03 11:10:00 【zpv2jdfc】
接上一篇 CPU缓存一致性问题
什么是伪共享
伪共享问题指两个线程A和B,他们俩写入同一个cache block的不同变量时,会导致另一个cpu核心的缓存失效的问题。我们来详细看一下伪共享问题到底是怎么产生的:
假设A线程要访问变量A,B线程要访问变量B,并且变量A和B会被分配到同一个cache line中:
接下来,A线程要读取变量A。此时A、B所在的cache line被加载到核心1的cache中,并且状态被标记为独占:
此时,B线程要访问变量B,那么这个cache line被加载到核心2的cache中。并且两个核心的cache line都标记为共享:
接下来,问题来了。假设A线程修改了变量A,为了保证数据一致性,就需要把核心2的cache line标记为失效:
这样一来,如果B要读取变量B的值,就需要A先将cache line写回内存,然后B再从内存中读取。也就是说,明明B变量自始至终都没有改变过,但是在访问时却需要重新从内存读取。如果A、B两个线程轮流修改变量A、B的话,伪共享问题会严重影响性能。
解决伪共享的办法
1.字节填充
对上面这种情况,如果A、B不被分配在同一个cache line中自然就不存在伪共享问题了。
如何让A、B分配在不同cache line中呢?我们可以通过这个命令查看cache line的大小
more /sys/devices/system/cpu/cpu1/cache/index0/coherency_line_size

可以看到cache line大小为64字节。接下来,我们来对比一下使用字节填充后程序性能会提高多少。
不使用字节填充:
public class Main {
public static void main(String[] args) throws InterruptedException {
Pair pair=new Pair();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 0x7fff_ffff; i++) {
pair.x++;
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 0x7fff_ffff; i++) {
pair.y++;
}
});
long start = System.currentTimeMillis();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(System.currentTimeMillis() - start);
}
}
class Pair{
// long x1,x2,x3,x4,x5,x6,x7;
volatile long x=0;
// long y1,y2,y3,y4,y5,y6,y7;
volatile long y=0;
}
63615
使用字节填充:
public class Main {
public static void main(String[] args) throws InterruptedException {
Pair pair=new Pair();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 0x7fff_ffff; i++) {
pair.x++;
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 0x7fff_ffff; i++) {
pair.y++;
}
});
long start = System.currentTimeMillis();
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(System.currentTimeMillis() - start);
}
}
class Pair{
long x1,x2,x3,x4,x5,x6,x7;
volatile long x=0;
long y1,y2,y3,y4,y5,y6,y7;
volatile long y=0;
}
10781
注意这里要用volatile关键字防止编译器优化指令。
2.使用@Contented 注解
@Contented注解原理也是字节填充,注解既可以加在字段,也可以加在类上。加在字段上表示这个字段单独占一个缓存行,加在类上表示类中所有字段都独占一个缓存行。
使用@Contented注解需要配置jvm参数 -XX:-RestrictContended,通过 -XX:ContendedPaddingWidth 可以修改填充的字节大小,有效值范围0 - 8192,默认是128字节。
边栏推荐
- 用于发票处理的 DocuWare,摆脱纸张和数据输入的束缚,自动处理所有收到的发票
- 多态详细讲解(简单实现买票系统模拟,覆盖/重定义,多态原理,虚表)
- 3D激光SLAM:LeGO-LOAM---两步优化的帧间里程计及代码分析
- VRRP协议的作用及VRRP+OSPF配置方法
- Dry goods!A highly structured and sparse linear transformation called Deformable Butterfly (DeBut)
- Realize 2d characters move left and right while jumping
- 跨链桥协议 Nomad 遭遇黑客攻击,损失超 1.5 亿美元
- 【Star项目】小帽飞机大战(九)
- for in 和 for of的区别
- 基于PHP7.2+MySQL5.7的回收租凭系统
猜你喜欢

MySQL数据库实战(1)

Cross-chain bridge protocol Nomad suffers hacker attack, losing more than $150 million

shell编程-测试

"Global Digital Economy Conference" landed in N World, Rongyun provides communication cloud service support

C#/VB.NET 从PDF中提取表格
【一起学Rust】Rust包管理工具Cargo初步了解

【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解

实至名归!九章云极DataCanvas公司荣获智能制造领域多项殊荣

How to retrieve IDC research reports?

Simple implementation of a high-performance clone of Redis using .NET (1)
随机推荐
巴比特 | 元宇宙每日必读:玩家离场,平台关停,数字藏品市场正逐渐降温,行业的未来究竟在哪里?...
Why is the new earth blurred, in-depth analysis of white balls, viewing pictures, and downloading problems
Skills required to be a good architect: How to draw a system architecture that everyone will love?What's the secret?Come and open this article to see it!...
【JS 逆向百例】某网站加速乐 Cookie 混淆逆向详解
Matplotlib
二叉搜索树(搜索二叉树)模拟实现(有递归版本)
【AppCube】数字孪生万物可视 | 联接现实世界与数字空间
ABAB-740新语法
笔试题:金额拆分
Cross-chain bridge protocol Nomad suffers hacker attack, losing more than $150 million
通过组策略安装软件和删除用户配置文件
Cookie和Session使用
fast planner中拓扑路径搜索
STM32入门开发 介绍SPI总线、读写W25Q64(FLASH)(硬件+模拟时序)
Fastjson反序列化
本周四晚19:00知识赋能第4期直播丨OpenHarmony智能家居项目之设备控制实现
完全背包问题的思路解析
浅谈SVN备份
微信多开批处理(自动获取安装路径)
干货!一种被称为Deformable Butterfly(DeBut)的高度结构化且稀疏的线性变换