并行编程为什么要休眠_是什么使并行编程变得困难?

并行编程为什么要休眠

多核就在这里,它们在这里留下来。 行业趋势表明,每个核心都有可能变得越来越小和变慢(请参阅我的帖子以了解原因)。 要提高具有多核的单个程序的性能,需要将该程序拆分为可以同时在多个核上运行的线程 。 实际上,这向程序员提出了在代码中寻找并行性的问题。 我注意到许多硬件设计人员不了解MT挑战(因为他们从未编写过MT应用)。 这篇文章是向他们展示这个巨大冰山的一角。

2011年5月26日更新:我也为并行编程编写了一个案例研究,您可能会感兴趣。
为什么很难找到并行性?
某些工作很容易并行化,例如,如果一个人要花8个小时来粉刷一个房间,那么两个并行工作的人可以在四个小时内对其进行粉刷。 同样,两个软件线程可以同时处理图片的两半,从而将图片从彩色转换为灰度的速度提高了2倍。 注意:属于此类的程序已经被并行化,例如科学计算工作负载,图形,photoshop甚至像ImageMagick这样的开源应用程序。
本质上还存在其他顺序的程序,例如,两个人的烹饪速度不能比一个人快2倍,因为该任务无法完全并行化:存在任务间依赖性,而厨师最终会在彼此之间等待次。 不幸的是,许多程序具有人为的任务间依赖关系,因为程序员是用ST的思维定势编写它们的。 例如,请考虑以下代码摘录自H.264参考代码(我已删除了不必要的细节以突出我的观点):
macroclock_output_data mb; //Global variable
for (...) // The OUTER loop
   decode_slice(...);
   if(mb->last_mb_in_slice)
       break;

void decode_slice(...)
    ...
    mb = ...
请注意,变量mb是如何在每次迭代中写入的,没有任何迭代会使用先前迭代所写入的mb。 但是,mb被声明为全局变量,可能是为了避免重复分配和释放。 这是合理的ST优化。 但是,从MT的角度来看,OUTER循环的循环迭代现在彼此之间具有依赖性,因此无法并行运行。 要并行化此代码,程序员必须首先确定依赖关系是人为的。 然后,他/她必须检查数千行代码,以确保不会错误地假定此假设。 最后,他/她必须更改整个代码以使mb成为局部迭代变量。 这一切是很难实现的(我并行的H.264 这一纸)。
情况就是这样:将人为的依赖项保留在代码中会限制并行性,错误地删除一个真实的依赖项会破坏程序,并且达到完美的平衡需要付出巨大的努力。 由于第一次很难正确识别所有依赖项,因此它们会出错并开始调试。
为什么调试困难?
调试多线程代码非常困难,因为错误会随机出现。 考虑以下:
假设两个线程T0和T1需要递增变量X。为此,C / C ++ / JAVA代码将是
X = X + 1
它们的汇编代码如下所示:(指令标记为AF)。
T0 T1
一个 负载X,R0 d 负载A,R0
增量R0 Ë 增量R0
C 商店R0,X F 商店R0,A
在两个线程都完成之后,程序员希望X增加2。 但是,当线程并发运行时,它们的指令可以以任何顺序交错。 X的最终值取决于交织(假设在两个线程尝试递增之前X为0)。 例如,
ABCDEF:X = 2(正确)
DEAFBC:X = 1(不正确)
ADBCEF:X = 1(不正确)
基本上,存在一个依赖关系,即D不应在C之前执行(或A不应在F之前执行)。 程序员错过了这种依赖性。 但是,该代码可以正常工作一半时间,因此无法跟踪错误或测试修复程序。 此外,传统的调试技术(如printf和gdb)变得无用,因为它们会扰乱系统,从而改变代码的行为并常常掩盖该错误。
为什么优化性能如此重要和具有挑战性?
MT的唯一目的是性能。 并行代码的第一个工作版本比串行版本慢是很常见的。 有两个常见原因:
仍然有太多的依赖项(真实的或人为的):程序员经常迭代地删除依赖项,有时甚至重写整个程序以减少这些依赖项。
争用硬件资源:如果某些争用的硬件资源(例如共享缓存)也可以使线程序列化。 程序员必须确定并减少这种争论。 请注意,识别这些瓶颈特别具有挑战性,因为硬件性能计数器不可靠。
经过几次迭代后,该代码已足以达到性能目标。
工作还没有到此结束。
与ST代码不同,MT代码具有复杂的不确定性交互作用,因此在硬件发生变化时,其性能可能会波动很大,而ST代码则在每个世代中都将变得更快。 例如,我有一个分支定界算法(16-Puzzle解算器),它将随着更多的内核而变慢,因为当更多线程正在运行时,该算法最终会走到另一条路径上。 即使是简单的内核(如直方图计算),在不同的输入或机器配置下,其行为也可能会非常不同(请参阅本文 )。 因此,并行程序员还担负着使代码对更改健壮的任务。
结论
我的目标不是教并行编程,而只是提供编写好的并行程序所需的味道。 这确实是一项复杂的工作,我断言,如果不实际编写并行程序,就不可能理解挑战。 对于那些还没有写过的人,这是我的行动呼吁:
编写一个并行程序来计算两个数组的点积,并使其完美缩放,4核4倍加速等。这很简单,但您会学到更多。
搜索关键字:pthreads或winthreads分别在linux或Windows上学习语法。 分享您的经验!
2011年5月30日更新:谢谢大家的反馈和读者群。 我写了第三篇有关并行编程的文章。 它描述了一种基于配置文件的解决方案,用于在并行程序中选择最佳任务粒度

参考: 什么使并行编程变得困难? 来自我们的JCG合作伙伴 Aater Suleman,来自Future Chips博客。


翻译自: https://www.javacodegeeks.com/2012/08/what-makes-parallel-programming-hard.html

并行编程为什么要休眠

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值