写点什么

如何让代码并发效率更高

  • 2013-08-13
  • 本文字数:2197 字

    阅读完需:约 7 分钟

随着计算硬件的快速发展,多核多处理器已经广泛应用于企业和个人环境中,开发人员利用多线程技术努力提高软件的计算速度,资深系统架构师 Gurudutt Kumar总结了如何让代码并发效率更高的实践经验。

Gurudutt 首先列举了几种影响软件可伸缩性的问题:

  • 效率低下的并行化:单片应用程序或软件无法有效使用可用的计算资源。您需要将应用程序组织成并行任务。在传统的不支持多线程的应用程序或软件中,我们会经常看到这个问题。这些应用程序在多核、多处理器、芯片多线程硬件上无法伸缩,并且无法实现更好的吞吐量。线程太多可能会和线程太少一样,都不会产生好的结果。
  • 串行瓶颈:在多个线程或进程之间共享数据结构的应用程序可能会有串行瓶颈。为了保持数据完整性,可能必须使用锁定和串行化技术(例如,读取锁、读写锁、写入锁、自旋锁、互斥等)将这些共享数据结构的访问串行化。设计得效率低下的锁可能会由于多个线程或进程之间的高度锁争用而导致串行瓶颈,从而尝试获取锁。这可能会潜在地降低应用程序或软件的性能。应用程序的性能可能会随着核心或处理器数量的增加而降低。
  • 对操作系统 (OS) 或运行时环境的过度依赖:您不能依赖操作系统、运行时环境或编译器来完成伸缩应用程序或软件所需的一切操作。但是,编译器和运行时环境可以帮助提供一定的优化,您不能依赖它们解决所有可伸缩性问题。例如,不能依赖 Java™ 虚拟机 (JVM) 通过自动并行来发现 Java 应用程序的最佳可伸缩的机会。
  • 工作负载的不平衡可能是一个瓶颈:工作负载的不均匀分布可能导致无法有效地利用计算资源。您可能必须将较大的任务划分成可以并行运行的较小的任务,还可能必须将串行算法更改为并行算法,以便提高性能和可伸缩性。
  • I/O 瓶颈:由于阻止磁盘输入 / 输出 (I/O) 或高网络延迟而导致的瓶颈可能会严重抑制应用程序的可伸缩性。
  • 无效的内存管理:在多核平台上,因为有很多处理单元,因此纯计算可能非常廉价,并且主要内存可能也不是问题,因为它正在变得越来越大。但是,内存带宽一直是一个瓶颈,因为所有处理器核心都贡献了一个通用的总线。无效的内存管理可能导致一些难以检测到的性能问题,比如伪共享。

以“避免内存争用”为例,Gurudut 做了解释:

在内存和缓存中,各种不同的核共享一个通用的数据区域,这需要在它们之间进行同步。当不同的核同时访问同一个数据区域时,会发生 _ 内存争用 _。在不同的核之间同步数据会因总线通信、锁定成本以及缓存缺失而有很大的性能损失。如果应用程序有多个线程,并且所有线程都更新或修改同一个内存地址,那么正如前面部分所讨论的那样,为了保持缓存一致性,可能会产生一次重大的乒乓效应。这会导致性能降低。

如何避免内存争用呢?Gurudut 认为“不要在核之间共享可写入的状态”:

  • 为了最大程度地减少内存总线通信,可以通过最小化共享位置 / 数据尽可能地减少核心交互,即使共享数据没有锁保护,而有一些硬件级别原子指令(如 Microsoft® Windows® 32 位平台上的 InterlockedExchangeAdd64)保护也是如此。
  • 减少线程之间的内存争用的一个方法是从多个线程中消除对共享内存区域的更新。例如,即便是在多个线程需要更新全局计数器或累计总数(如统计数据)时,各个线程也可以保持线程本地总数,并让全局总数仅在需要时通过一个通用的线程进行更新。因此,在共享内存区域上的争用会大大减少。
  • 趋向于减少锁争用的模式会减少内存通信,因为它是一个共享的可写入状态,该状态需要使用锁并产生争用。

对于锁争用,Gurudut 认为要从“避免”和“减少”两个方面来解决这个问题:

避免

  • 避免在数据结构中发生锁争用的方法之一是采用并发数据结构设计和无锁算法,这会消除锁以及传统的同步技巧(比如互斥)。有多种并发数据结构的设计并不需要利用同步机制,比如互斥。
  • 无锁算法的一些示例如下:
    • 使用 相对论编程 的可伸缩并发哈希表:该技巧的最简单示例是 Read Copy Update (RCU) ,它专用于 Linux 内核,大大提高了 Linux 内核的性能,并简化了 Linux 内核的代码。
    • 无锁可扩展有序分割的哈希列表:这个无锁递归可扩展哈希算法使用了无锁的链接列表,这些列表使用原子指令来修改链接的列表。
  • 在 Linux 内核中,广泛使用了每处理器变量,系统上的每个处理器都获得了自己的一个给定变量的副本。访问每处理器变量不需要使用锁,此外,因为在不同的处理器上,这些变量未在线程之间共享,因此没有伪共享或内存争用。这种技巧非常适合收集统计信息。

减少

  • 当使用传统锁或同步技巧(如自旋锁)时,必须注意的是,不要使用单片锁或全局锁,而是将这些锁分成更细小的部分。因此,锁会保护数据结构中的某个特定区域以及较小的区域。这样多个线程就能够通过获取保护这些成员的相应锁,在同一数据结构的不同成员上并发进行操作。这种方法可以实现更多并发。
  • 甚至当软件设计中的同步机制能够实现更好的并发和减少锁争用时,也可能会由于伪共享而导致发生性能问题。例如,考虑一个哈希数据结构。如果存在一个自旋锁数组,用于保护哈希中的每个哈希桶,那么在自旋锁数组中可能会出现伪共享。两个线程在两个不同的处理器上运行,每个线程都锁定哈希中的不同哈希桶,那么当它们所需的自旋锁位于同一个缓存行上时,可能会发生伪共享。因此,在设计此类算法时需要考虑采用避免发生伪共享的通用技巧。

作者的微信公众号“老崔瞎编”,关注 IT 趋势,承载前沿、深入、有温度的内容。感兴趣的读者可以搜索 ID:laocuixiabian,或者扫描下方二维码加关注。

2013-08-13 03:156610
用户头像

发布了 501 篇内容, 共 284.7 次阅读, 收获喜欢 64 次。

关注

评论

发布
暂无评论
发现更多内容

Apache Doris 2.1.6 版本正式发布

SelectDB

数据仓库 数据分析 LakeHouse 物化视图

LED厂家告诉您LED玻璃幕墙如何设计

Dylan

设计 艺术 LED LED display LED显示屏

《科研智能(AI4R&D)——人工智能驱动的研发新范式》正式发布

中国信通院AI Infra工作组

阿里巴巴拍立淘API返回值:商家优化商品信息的深度指南

代码忍者

API 测试 pinduoduo API

【Tomcat源码分析】从零开始理解 HTTP 请求处理 (第一篇)

派大星

tomcat源码解读

大模型训练平台标准第三次研讨会即将召开

中国信通院AI Infra工作组

中国信通院可信人工智能基础平台(AI Infra)评估工作正式启动

中国信通院AI Infra工作组

探索高质量大模型推理平台建设路径——大模型推理标准第二次研讨会即将召开

中国信通院AI Infra工作组

云南大理等级保护测评机构在哪里?电话多少?

行云管家

等保 云南

“前沿思享会:探索AI+材料新边界”闭门研讨会顺利召开

中国信通院AI Infra工作组

VMware Live Site Recovery 9.0.2 发布下载,新增功能概览

sysin

vmware esxi

中国信通院启动科研智能(AI4R&D)重点标准化方向及参编专家征集工作

中国信通院AI Infra工作组

万界星空科技电线电缆行业MES系统核心功能

万界星空科技

mes 万界星空科技 电线电缆行业 电线电缆mes

一文说清楚ETL与Kafka如何实现集成

谷云科技RestCloud

kafka 数据处理 分析 ETL 数据集成

虚拟人,如何用好这个“外挂”?一定要看看这本书!

博文视点Broadview

探索高质量大模型训练平台建设路径——大模型训练标准第三次研讨会顺利召开

中国信通院AI Infra工作组

AI助力低代码平台:从智能化到高效交付的全新变革

天津汇柏科技有限公司

低代码 AI 人工智能

可信AI评估|中国信通院可信AI“大模型一体机”第二批评估正式启动

中国信通院AI Infra工作组

海尔连续3年蝉联生态品牌认证“领航者”,飞书获评“突破者” ,共建生态绿洲

ToB行业头条

助力企业降低成本,ByteHouse打造新一代“弹性”云数仓

字节跳动数据平台

数据库 大数据 云原生 Clickhouse 数仓

中国信通院边缘人工智能平台标准首轮评估正式启动

中国信通院AI Infra工作组

中国人工智能产业发展联盟正式发布《科研智能(AI4R&D)——人工智能驱动的研发新范式》

中国信通院AI Infra工作组

华为全联接大会2024︱鲲鹏计算产业峰会成功举办

极客天地

京东商品属性的详细api数据解析:颜色、尺寸与材质

技术冰糖葫芦

API Gateway API 接口 API 测试 pinduoduo API

云栖大会Day1:云应用开发平台 CAP 来了

阿里巴巴云原生

阿里云 云原生 云栖大会

Amazon Bedrock 模型微调实践(二):数据准备篇

亚马逊云科技 (Amazon Web Services)

人工智能

活动预告:“大模型时代下AI中台”主题沙龙

中国信通院AI Infra工作组

如何让代码并发效率更高_语言 & 开发_崔康_InfoQ精选文章