写点什么

PDC 09:PLINQ 使用过程中常见性能问题及应对方案

  • 2009-12-06
  • 本文字数:1817 字

    阅读完需:约 6 分钟

在上月举行的 PDC 09 大会上,微软并行库团队的开发工程师 Igor Ostrovsky 介绍了 PLINQ 的工作原理,以及多核编程中,尤其是在 PLINQ 使用过程中几种常见性能问题及应对方法。Igor 表示,这些性能问题很少在顺序编程中遇到,因此在并行环境中容易被人忽视。

第一个性能问题是内存分配。由于利用了多核 CPU 进行运算,对象分配的速度也加快了。此外,程序中可以还会出现更高频率的字符串连接或装箱操作,这都会使 GC 压力增大。.NET 应用程序所使用的默认 GC 方式为 Concurrent GC,它的性能很高,并且为降低应用程序的延迟作了很多优化。它的最佳使用场景是用户交互式应用,这样可以尽可能避免用户界面的停顿,但是它在长期运行的多核程序中表现并不好。而最终的结果是大量计算时间耗费在 GC 上,此时应用程序算法即便是利用了多个核,也会发现它的伸缩能力受到了 GC 限制。解决这个问题的方法之一是减小内存分配,例如可以使用值类型来代替引用类型。值类型的对象会分配在线程栈而不是堆上,以此避免对 GC 产生压力。第二个方法是在 config 文件中启用 Server GC。使用 Server GC 会改变.NET 分配对象的方式,此时.NET 会为每个核准备不同的堆,并且独立进行垃圾回收。这样在一台 4 核的机器上便可以有 4 个线程同时进行垃圾回收,性能自然也就随着多核而提升了。

第二个性能问题是 CPU 在局部化(Locality)和缓存方面的问题。在流行的多核架构中,每个核都有独立的二级缓存。CPU 并不会缓存单个地址中的数据,而是缓存以 64 字节或 128 字节相邻内存的缓存条目(cache line),因此当某个核改变了内存中的数据时,则其他核中地址相邻的缓存数据也会失效,这样 CPU 每次进行计算时都要从速度较慢的内存中加载数据。这个性能问题的隐蔽之处在于代码中的不同数据——例如同一个数组的不同下标——可能在内存中处在同一个缓存条目中,因此这个问题又被称为错误共享(False Sharing)。Igor 演示了一段性能低下的代码,在这个实现中多个线程会不断读写同一个数组的相邻下标,因此造成了错误共享。Igor 的修改方法是将数据存放在数组中相距较远的下标,甚至是不同的数组中。由于 CPU 的缓存条目大小有限,这种方法可以避免出现错误共享。博客园老赵在《计算机体系结构与程序性能》一文中也提出了一种优化方式,他的做法是尽可能使用局部变量来保存计算过程中的中间值,以此减少对数组的修改操作。由于局部变量分处不同线程的栈空间内,因此地址相距很远,不会造成错误共享问题。当有人问起到这种优化方式是否安全时,Igor 答到,这其实和 CPU 架构的实现方式有很大关系。如果某一天缓存实现变化了,可能这种优化方式会适得其反。不过在目前主流架构中,这样的做法是比较安全的。Igor 补充道,他认为这也是为什么“全自动”并行化那么困难的原因之一,因为在并行环境下影响程序性能的方面实在太多了。

第三个问题在于开发人员倾向于在 PLINQ 中使用大量小粒度的委托来完成工作,此时每个委托的计算任务很小,而委托的执行次数会很多。在计算较长的序列时,小粒度的委托对象也能获得性能提高,但是它会产生额外的负载。例如,MoveNext 和 Current 的调用,以及每个委托的执行性能都和虚方法比较接近。此外,一个较长的输入序列也会受限于内存的吞吐量。因此,Igor 建议开发人员在使用 PLINQ 时尽可能使用计算量较大的委托,以此减少计算主体外的性能开销。

第四和第五问题则与 PLINQ 的实现有关。Igor 表示,PLINQ 可以并行执行所有的 LINQ 查询,但是相对于复杂的 LINQ 查询,PLINQ 能够对简单的 LINQ 操作有更好的优化。因此,Igor 建议开发人员在使用 PLINQ 时可以手动将复杂的 LINQ 表达式拆分为简单的 LINQ 查询,并且只在真正需要大量计算的地方才开始并行化。这种结合顺序执行和并行执行的方式,可以让应用程序的性能达到最优。此外,为不同的输入方式选择不同的分块(partition)策略对性能的影响很大,因此 PLINQ 会对数组和 IList<> 进行静态的分割,而对 IEnumerable<> 集合按实际需求进行划分,而开发人员也可以通过自定义 Partitioner 的方式来指定特别的分割策略。

最后,Igor 强调,使用并行计算进行程序性能优化之前,一定要通过合适的评测方式来找到代码的瓶颈。如果这个瓶颈正符合数据并行(data parallel)模式,那么可以使用 PLINQ 进行性能优化。而优化完成后还需要评测其效果,并使用之前提出的几种方案进行合适的调整。

你可以在 PDC 2009 的网站上浏览或下载本次演讲的完整录像及幻灯片等资源。

2009-12-06 08:133258
用户头像

发布了 157 篇内容, 共 61.9 次阅读, 收获喜欢 6 次。

关注

评论

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

基于开发者空间OpenGauss数据库的PLPGSQL实践一

华为云开发者联盟

opengauss #SQL 华为开发者空间

手把手教你搭建MCP服务器

测吧(北京)科技有限公司

#人工智能 MCP

通义万相即将开源一款「语音转视频」模型;微软开源长篇幅、多角色 TTS 模型 VibeVoice丨日报

声网

GreatSQL优化技巧:手动实现谓词下推

GreatSQL

星环科技ArgoDB:以“硬件-生态-合规”三轴驱动,构建国产化替代的产业引擎

星环科技

智慧物流车辆管理平台:全链路数字化解决方案

微擎应用市场

短剧在线播放系统:专业化平台解决方案

微擎应用市场

自动化智能体体系介绍

测吧(北京)科技有限公司

外资企业购买堡垒机必要性简单分析

行云管家

网络安全 数据安全 堡垒机

Apache SeaTunnel闪耀2025中国数据库技术大会,荣获「年度优秀技术团队奖」

白鲸开源

数据库 大数据 数据同步 数据集成 Apache SeaTunnel

【新版发布】Apache DolphinScheduler 3.3.1 正式上线:更稳、更快、更安全!

白鲸开源

大数据 开源 大数据任务调度 Apache DolphinScheduler 发版

哈尔滨二级等保:为中小企业网络安全筑牢坚实防线

等保测评

数据流向何方?一文掌握 Apache SeaTunnel Sink 连接器全生态 (2024版)

白鲸开源

大数据 开源 数据同步 数据集成 Apache SeaTunnel

知识图谱与RAG融合实战:用LightRAG极速构建智能问答系统

测吧(北京)科技有限公司

学Go必看的进阶面试题「刷起来」

王中阳Go

Go 面试题

精准测试平台

测试人

DolphinScheduler API与SDK实战:版本管理、系统集成与扩展全指南

白鲸开源

大数据 开源 Apache DolphinScheduler API 管理 任务调度平台

大模型性能测试完全指南:从原理到实践

测试人

人工智能 软件测试 测试开发

开源协同驱动能源管理革新:MyEMS 如何重塑行业生态

开源能源管理系统

开源 能源管理系统

使用Amazon Verified Permissions快速为Express应用API添加安全防护

qife122

谁是中国第一台光子CT的创造者,水落石出

先锋IT

25年贵州等保测评机构名单(已整理)

行云管家

等保 等保测评 等保合规

大数据时代的新闻数据分析:舆情研判与决策支撑

沃观Wovision

数据分析 新闻 沃观Wovision

迈特趣视频创作 SaaS 系统:视频变现新工具

微擎应用市场

数字人超级大师:微擎生态下的高保真 AI 数字人解决方案

微擎应用市场

ManageEngine卓豪-衡量事件响应影响指标-MTTR

ServiceDesk_Plus

ManageEngine卓豪

基于开发者空间OpenGauss数据库的PLPGSQL实践二

华为云开发者联盟

sql opengauss 华为开发者空间

从入门到精通:什么是态势感知

沃观Wovision

态势感知 海外舆情监控 沃观Wovision

仓颉之反射和注解的神秘力量

华为云开发者联盟

注解 反射 仓颉 华为开发者空间

零碳园区:绿色转型的关键实践与智慧支撑

开源能源管理系统

开源 能源管理系统

AI应用进化论(上):Fabarta个人专属智能体如何找准场景与功能

Fabarta

人工智能 智能体 AI助手

PDC 09:PLINQ使用过程中常见性能问题及应对方案_.NET_赵劼_InfoQ精选文章