当前位置: 首页 > news >正文

伪共享问题如何解决?

伪共享问题是多核处理器环境下常见的性能瓶颈之一,特别是在多线程编程中。想要解决它,就必须先了解缓存行的概念。

缓存行

缓存行是指在 CPU 缓存中最小的数据单位,通常包含一定数量的字节(例如,常见的缓存行大小为 64 字节)。当处理器从主内存读取数据时,它不仅读取请求的字节,还会读取周围的数据形成一个缓存行,以减少未来的内存访问次数。这样做的好处是可以减少内存访问的频率,提高缓存命中率,从而提升性能。

缓存行对齐

缓存行对齐是指将数据的存储位置调整为缓存行大小的整数倍,以便CPU可以一次加载整个数据。

为什么需要缓存行对齐?

当CPU访问主存中的数据时,它通常会加载整个缓存行到缓存中。如果数据没有正确地对齐到缓存行边界,那么CPU可能需要多次访问主存以获取完整的数据。这被称为缓存行分裂(Cache Line Splitting),它会导致额外的性能开销。通过缓存行对齐,我们可以减少缓存行分裂的发生,从而提高程序的性能。

如何在JVM中应用缓存行对齐?

在JVM中,我们可以通过调整对象的布局来实现缓存行对齐。以下是一些建议:

  • 避免在对象内部跨越缓存行边界的访问:如果对象的字段跨越了缓存行边界,那么访问这些字段可能会导致缓存行分裂。为了避免这种情况,我们应该确保对象的所有字段都位于同一个缓存行内。
  • 使用填充(Padding):我们可以使用特定类型的字段(如long或double)作为填充,以确保对象的大小是缓存行大小的整数倍。这样,无论对象如何排列,其边界都将与缓存行边界对齐。
    示例见结尾。
  • 考虑对象的访问模式:当多个对象被频繁地一起访问时,我们应该考虑将这些对象排列在一起,以便它们可以一次性加载到缓存中。
  • 使用太阳花(Sunflower)策略:这是一种对象布局策略,通过将对象分组到不同的“太阳花”中,可以确保在同一时间访问的对象位于不同的缓存行中,从而减少缓存行争用。
  • 使用数组:将多个变量存储在一个数组中,每个变量占据数组中的一个元素,这样它们自然分布在不同的缓存行中。
    class ThreadSafeData {volatile long[] variables = new long[2]; // 假设缓存行大小为 64 字节,每个 long 占 8 字节// 线程 1 访问 variables[0]// 线程 2 访问 variables[1]
    }
    

使用填充技术的示例:

package org.hbin;import java.util.ArrayList;
import java.util.List;/*** @author Haley* @version 1.0* 2024/8/21*/
public class CacheLineWithPadding {private static long count = 10000_0000L;public static class Data {// 使用7个long类型填充,占用7*8=56字节public volatile long p1, p2, p3, p4, p5, p6, p7;public volatile long value; // 占用8字节
//        public volatile long p8, p9, p10, p11, p12, p13, p14;}public static Data[] array = {new Data(), new Data()};public static long test() {Thread t1 = new Thread(() -> {for (long i = 0; i < count; i++) {array[0].value = i;}});Thread t2 = new Thread(() -> {for (long i = 0; i < count; i++) {array[1].value = i;}});long start = System.currentTimeMillis();try {t1.start();t2.start();t1.join();t2.join();} catch (Exception e) {e.printStackTrace();}return System.currentTimeMillis() - start;}public static void main(String[] args) {List<Long> list = new ArrayList<>();for (int i = 0; i < 10; i++) {list.add(test());}System.out.println(list);System.out.println(list.stream().mapToLong(Long::longValue).average().orElse(0.0));}
}

运行上面的代码,观察输出时间;注释上述代码16行public volatile long p1, p2, p3, p4, p5, p6, p7;,两次运行代码,你可以看到运行时间明显增加了。正是因为有这一行中声明的7个long类型的数据填充,使得缓存更加高效。

放开18行注释掉的代码public volatile long p8, p9, p10, p11, p12, p13, p14;,运行程序并将结果和当前进行对比,性能应该也会略有提升的哟!你知道原因么?

jdk8的解决方式

jdk1.8中,官方已经提供了对伪共享的解决办法,那就是sun.misc.Contended注解,有了这个注解解决伪共享就变得简单多了。

@sun.misc.Contended
public static class Data {public volatile long value;
}

默认情况下此注解是无效的,需要在JVM启动时开启这个注解。
设置方式:-XX:-RestrictContended

伪共享问题

伪共享(False Sharing)是指多线程程序中,多个线程访问不同变量,但这些变量位于同一个缓存行中。当一个线程更新这个缓存行中的一个变量时,会导致整个缓存行被刷新到主内存中,从而可能导致其他线程读取该缓存行时需要从主内存中重新加载,造成不必要的性能损失。
Disruptor项目的经典示例图演示了伪共享的问题,如下:
在这里插入图片描述
上图中,一个运行在处理器 core1上的线程想要更新变量 X 的值,同时另外一个运行在处理器 core2 上的线程想要更新变量 Y 的值。但是,这两个频繁改动的变量都处于同一条缓存行。
根据MESI协议(不清楚的小伙伴请自行参考我写的另一篇文章,详细介绍了MESI协议),两个线程就会轮番发送 RFO 消息,占得此缓存行的拥有权。当 core1 取得了拥有权开始更新 X,则 core2 对应的缓存行需要设为 I 状态。当 core2 取得了拥有权开始更新 Y,则 core1 对应的缓存行需要设为 I 状态。轮番夺取拥有权不但带来大量的 RFO 消息,而且如果某个线程需要读此行数据时,L1 和 L2 缓存上都是失效数据,只有 L3 缓存上是同步好的数据。要知道,读 L3 的数据非常影响性能。更坏的情况是跨槽读取,L3 都要 miss,只能从内存上加载。
表面上 X 和 Y 都是被独立线程操作的,而且两操作之间也没有任何关系。只不过它们共享了一个缓存行,但所有竞争冲突都是来源于共享。

伪共享的解决方案

在实际的生产开发过程中,我们一定要通过缓存行填充去解决掉潜在的伪共享问题吗?
其实并不一定。
首先伪共享是很隐蔽的,我们暂时无法从系统层面上通过工具来探测伪共享事件。其次,不同类型的计算机具有不同的微架构(如 32 位系统和 64 位系统的 java 对象所占自己数就不一样),如果涉及到跨平台的应用,那就更难以把握了,一个确切的填充方案只适用于一个特定的操作系统。
其次,缓存的资源是有限的,如果填充会浪费珍贵的 cache 资源,并不适合大范围应用。最后,目前主流的 Intel 微架构 CPU 的 L1 缓存,已能够达到 80% 以上的命中率。

相关文章:

伪共享问题如何解决?

伪共享问题是多核处理器环境下常见的性能瓶颈之一&#xff0c;特别是在多线程编程中。想要解决它&#xff0c;就必须先了解缓存行的概念。 缓存行 缓存行是指在 CPU 缓存中最小的数据单位&#xff0c;通常包含一定数量的字节&#xff08;例如&#xff0c;常见的缓存行大小为 …...

基于web框架的协同过滤的美食推荐系统【数据爬虫、管理系统、数据可更新、样式可调整】

文章目录 有需要本项目的代码或文档以及全部资源&#xff0c;或者部署调试可以私信博主项目介绍研究背景研究的目的与意义协同过滤算法基于用户的协同过滤算法定义基于物品的协同过滤算法的定义 数据库设计db_food&#xff08;美食信息表&#xff09;db_collect&#xff08;美食…...

Eureka中的多实例配置:如何处理微服务实例动态扩展与缩减

Eureka中的多实例配置&#xff1a;如何处理微服务实例动态扩展与缩减 1. 引言 在微服务架构中&#xff0c;服务的动态扩展与缩减是确保系统弹性和高可用性的关键因素。Eureka&#xff0c;作为一个服务注册和发现的组件&#xff0c;扮演着至关重要的角色。它由Netflix开源&…...

Ubuntu 22.04使用 IPTables 配置防火墙

网络安全管理是服务器安全的重要组成部分。在这将介绍在 Ubuntu 22.04 中使用名为 iptables 的软件包管理工具设置防火墙的过程。 IPTables简介 IPTables是一个功能强大的软件包管理工具&#xff0c;可用于大多数Linux发行版&#xff0c;包括Ubuntu 22.04。该工具允许管理员定…...

Java语言程序设计——篇十三(1)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 欢迎大家&#xff1a;这里是我的学习笔记、总结知识的地方&#xff0c;喜欢的话请三连&#xff0c;有问题可以私信&#x1f333;&#x1f333;&…...

GB/T 5023.3-2008额定电压450/750V及以下聚氯乙烯绝缘电缆

聚氯乙烯绝缘电缆产品分为固定布线用无护套电缆、固定布线用护套电缆、轻型无护套软电缆、一般用途护套软电缆、安装用电线和屏蔽电线、特殊用途护套软电缆、聚氯乙烯绝缘阻燃/耐火电缆等产品。 GB/T 5023.3-2008额定电压450/750V及以下聚氯乙烯绝缘电缆 第3部分&#xff1a;固…...

深入单例模式

1. 饿汉模式 饿坏了&#xff0c;上来就先实例化一个对象&#xff0c;好处是代码简单&#xff0c;坏处是这个对象后面如果一直用不到&#xff0c;就是个浪费。 public class A{ private static A a new A(); private A(){} public static A getInstance(){ return a; } } 2. 懒…...

MongoDB 单机和集群环境部署教程

目录 一、MongoDB 单机环境部署1. 环境准备2. 安装 MongoDB2.1 在 Ubuntu 上安装 MongoDB2.2 在 CentOS 上安装 MongoDB2.3 启动 MongoDB 服务2.4 验证 MongoDB 安装2.5 MongoDB 基本安全设置 3. 单机部署注意事项 二、MongoDB 集群环境部署1. 环境准备2. MongoDB Replica Set …...

【学习笔记】Day 20

一、进度概述 1、机器学习常识12-18&#xff0c;以及相关代码复现 二、详情 12、SVM&#xff08;support vector machines&#xff0c;支持向量机&#xff09; 实际上&#xff0c;支持向量机是一种二分类模型&#xff0c;它将实例的特征向量映射为空间中的一些点&#xff0c;…...

StringBuffer与StringBuilder 2024-8-21 22-13

目录 一、StringBuffer二、StringBuilder三、总结 一、StringBuffer StringBuffer是一个可变的字符序列&#xff0c;它的存在是为了解决频繁操作字符串时产生大量临时对象的问题。 构造方法&#xff1a; StringBuffer()&#xff1a;创建一个空的字符串缓冲区&#xff0c;初始容…...

会声会影剪辑视频收费吗,会声会影最新破解版

会声会影2024&#xff1a;引领视频创作新时代的创新之旅** 在数字时代的浪潮中&#xff0c;视频创作已成为连接世界、表达创意的重要方式。随着技术的不断进步&#xff0c;一款名为“会声会影2024”的视频编辑软件横空出世&#xff0c;它不仅继承了前代产品的优秀传统&#xf…...

在Windows11强制开启copilot

在 Windows 11 上启用自带的基于 GPT-4 的 Copilot 功能。以下是具体步骤&#xff1a; 更新系统&#xff1a; 确保你的 Windows 11 系统已经更新到最新版本&#xff08;23H2 或更高版本&#xff09;。你可以在“设置” > “Windows 更新”中检查并安装最新更新。 更改区域和…...

基于Java的开源CMS有哪些推荐,各自特点是什么

最强大、最易用的CMS&#xff0c;向大家做一个简要介绍。 01 Alfresco Alfresco是一个开源的企业网站内容管理系统&#xff0c;它提供了文档管理、多人协作、记录管理、知识管理网页内容和图像管理等功能。它使用Spring、 Hibernate、 Lucene 和JSF等最新java技术构建了模…...

IPC进程通信以及网络通信

一、IPC 进程间通信方式 共享内存 //最高效的进程间通信方式 不需要把用户的东西再复制到内核 他们与内核进行绑定 共享内存&#xff1a; 1、是一块&#xff0c;内核预留的空间 2、最高效的通信方式 //避免了用户空间到内核空间的数据拷贝 IPC通信方式 ---操作流程类似的…...

【脏数据 bug 解决】ValueError: mean must have 1 elements if it is an iterable, got 3

问题描述&#xff1a; 在训练模型的过程中&#xff0c;出现 clip_image_processor 无法处理数据的问题&#xff0c;说明数据集中很可能出现了脏数据。本文使用的数据为 LAION-Aesthetics-V2-6.5plus&#xff0c;从 https://dagshub.com/DagsHub-Datasets/LAION-Aesthetics-V2-…...

【Vue3】集成 Ant Design Vue

【Vue3】集成 Ant Design Vue 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗…...

如何处理前端项目中的SEO优化:从SPA到SSR与SSG

如何处理前端项目中的SEO优化&#xff1a;从SPA到SSR与SSG 在前端开发的日常工作中&#xff0c;你可能经常会遇到这样的情况&#xff1a;辛辛苦苦写了一个功能丰富、界面炫酷的单页应用&#xff08;SPA&#xff09;&#xff0c;但上线后发现搜索引擎的表现却不尽如人意。页面内…...

【UE5】Groom毛发系统的基本使用——给小白人添加头发

目录 效果 步骤 一、准备 二、使用3DsMax制作毛发 三、在UE中给小白人安装毛发 四、修改毛发材质 效果 步骤 一、准备 1. 新建一个第三人称模板工程 2. 在项目设置中&#xff0c;勾选“支持计算蒙皮缓存” 3. 在插件面板中&#xff0c;启用“Groom”和“Alembic Gro…...

DataWorks函数

文章目录 0、MaxCompute预置的函数分类1、日期函数2、数学函数3、算术运算符4、窗口函数5、聚合函数6、字符串函数7、复杂类型函数8、加密函数9、其他函数 0、MaxCompute预置的函数分类 函数类型说明日期函数支持处理DATE、DATETIME、TIMESTAMP等日期类型数据&#xff0c;实现…...

设计模式学习优质网站分享:refactoring.guru

地址 英文版地址&#xff1a;https://refactoring.guru/design-patterns 中文版地址&#xff1a;https://refactoringguru.cn/design-patterns 介绍 这个网站是专门学习 设计模式 和 软件重构 的网站 整体来说并不花哨&#xff0c;但我觉得他最大的优点就是&#xff1a; 概…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing

Muffin 论文 现有方法 CRADLE 和 LEMON&#xff0c;依赖模型推理阶段输出进行差分测试&#xff0c;但在训练阶段是不可行的&#xff0c;因为训练阶段直到最后才有固定输出&#xff0c;中间过程是不断变化的。API 库覆盖低&#xff0c;因为各个 API 都是在各种具体场景下使用。…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

快速排序算法改进:随机快排-荷兰国旗划分详解

随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...