acm-header
登录

ACM通信

实践

Photoshop的可扩展性:保持简单


克莱姆·科尔和拉塞尔·威廉姆斯

克莱姆·科尔(左)和拉塞尔·威廉姆斯

信贷:理查德Mortgenstein

回到顶部

在过去的20年里,Adobe Photoshop已经成为世界范围内数字摄影爱好者、艺术家和平面设计师事实上的图像编辑软件。它的广泛吸引力部分与用户界面有关,它可以相当直接地应用一些极其复杂的图像编辑和过滤技术。然而,在façade的背后,有许多复杂的、需要计算的代码。为了提高这些计算的性能,Photoshop的设计师们在20世纪90年代中期开始尝试采用并行技术,当时最先进的桌面系统需要两个或四个处理器。在当时,Photoshop是唯一一个提供这种功能的桌面应用程序。

Photoshop的并行性,诞生于专业扩展卡的时代,在过去十年出现的二核和四核机器上,已经成功地实现了良好的扩展。然而,当Photoshop的工程师们为即将到来的8核和16核计算机做准备时,他们已经开始遇到越来越多的缩放问题,主要是Amdahl定律和内存带宽限制的结果。

在这个ACM案例研究中,Adobe Photoshop首席科学家拉塞尔•威廉姆斯说话Clem科尔英特尔集群准备项目的架构师,关于Photoshop团队如何应对这些挑战。尽管它们目前的位置代表了并行计算领域的不同方面,但它们都有在操作系统级别处理并行的悠久历史。

在加入Photoshop开发团队之前,Williams曾长期担任操作系统设计师,在苹果公司(Apple)和Elxsi等公司工作,他负责开发Copland微内核,并帮助开发微型超级计算机。这种背景的多样性现在使他能够在堆栈的不同层次上对并行性保持全面的观点。

Cole是一位经验丰富的操作系统开发人员,在Unix内核和工具开发方面有着多年的经验。他目前正在努力改进利用英特尔下一代多核芯片的多处理器的方法,这使他成为威廉姆斯合适的面试官,威廉姆斯的工作很大程度上建立在科尔在英特尔帮助创建的平台之上。

虽然Photoshop带来了一系列独特的问题和限制,但它带来的许多工程挑战对于任何曾经尝试在应用程序中实现并行的软件工程师来说无疑是熟悉的。尽管如此,为了解决Photoshop工程师今天面临的问题,我们必须首先考虑应用程序在过去15年里的并行性历史。

科尔:您编写软件已经有很长一段时间了,在过去的11年里,您一直在使用Photoshop,并越来越多地参与到它的并行方面。哪些部分被证明是容易的,哪些部分被证明是出乎意料的困难?

WILLIAMS:简单的部分是,Photoshop实际上已经有相当多的并行性很长时间了。在一个非常简单的级别上,它有一些工作线程来处理异步游标跟踪之类的事情,同时还管理另一个线程上的异步I/O。让这类事情运作起来非常简单,因为问题很简单。跨边界共享的数据很少,我们的目标不是获得计算伸缩性;这只是为了让异步任务运行起来。

然而,我应该注意的是,即使是排队磁盘I/O请求这样一个非常简单的任务,以便它们可以由另一个线程异步处理,我所知道的Photoshop中唯一存活时间最长的bug最终还是隐藏在代码中。它在那藏了十年。我们将打开异步I/O,并最终解决这个bug。我们可能会花上数周的时间去寻找它,但最后却不得不放弃,并在不开启异步I/O的情况下发布应用。每过几个版本,我们就会重新打开它,这样我们就可以再次开始寻找漏洞。

科尔:我记得巴特勒·兰普森说过串行机器的奇妙之处在于你可以暂停它们,然后查看所有东西。当我们并行工作时,总会有其他事情发生,所以停下一切去检查它的概念真的很难。你的bug能在I/O系统中隐藏那么长时间,我一点也不震惊。

WILLIAMS:这是一个非常简单的问题。就像Photoshop的许多其他方面一样,这与这个应用程序最初是为Macintosh编写的,然后转移到Windows系统有关。在Macintosh上,设置文件位置调用是单个调用,而在Windows上,它是一对调用。把它放在那里的人没有考虑到这样一个事实,即当您在线程间共享文件位置时,这对调用必须是原子的。

科尔:当然,现在回过头来看,你会说这是显而易见的。

WILLIAMS:事实上,最初在代码中添加bug的人在我们开始寻找bug时走在走廊上,拍了拍他的额头,然后在10年后才意识到问题所在。

总之,在Photoshop中,我们在并行处理方面取得成功的另一个重要领域是基本的图像处理程序。当你在Photoshop中运行一个滤镜或调整时,它会被分解成许多基本的图像处理操作,这些操作是在一个通过跳转表访问的库中实现的。在早期,这使得我们能够发布这些所谓的“瓶颈例程”的加速版本。在20世纪90年代,当公司出售用于加速Photoshop的专用DSP(数字信号处理器)卡时,我们可以修补这些瓶颈,在加速卡上执行我们的程序,然后将控制返回到68KB处理器上。

这为我们提供了一个很好的机会,以一种不会使我们的瓶颈例程算法的实现复杂化的方式将并行性放入应用程序中。当调用其中一个例程时,它将被传递一个或两个或三个指针到内存中的字节。它无法访问Photoshop基于软件的虚拟内存,也无法调用操作系统;最下面只是一个数学程序。这为我们提供了一个非常简单的方法,可以在进入数学程序之前插入一些东西,将我们想要在多个CPU上处理的内存分片,然后将这些内存块交给每个CPU上的线程。

科尔:关键是你有一个对象可以被分解成更小的对象,而上层部分不需要担心它。这也有助于你有一个漂亮,干净的地方进行分裂。

WILLIAMS:另一个好的方面是底部的东西不需要知道同步。它仍然只是一个数学例程,传递一个源指针,或者可能是两个源指针,然后用一个目标指针进行计数。所有的同步都存在于多处理器插件中,该插件将自己插入到瓶颈例程的跳转表中。这个架构在1994年被放到了Photoshop中。它使我们能够利用Windows NT的对称多处理架构,无论是2个cpu还是4个cpu,这是当时在非常高端的机器上所能得到的。它还允许我们利用Macintosh上的DayStar多处理API。在20世纪90年代中后期,你可以从DayStar Digital公司购买多处理器机器,Mac操作系统的其他部分无法利用这些机器,但Photoshop可以。

十多年来,Photoshop一直使用多个处理器来执行它对像素进行的基本图像处理工作。这已经大大超过了过去十年中人们在一个系统中通常能够获得的cpu数量,也就是两个或四个处理器。从本质上讲,这些系统中没有出现同步错误。

科尔:这是一个惊人的说法!你能分享一下与此相关的见解吗?你觉得我们其他人能从中学到什么?

WILLIAMS:我认为最大的胜利在于不必为将要并行化的处理例程编写同步。换句话说,人们可以写卷积核或者任何他们需要做的关于像素处理的东西而不用担心所有的同步问题。如果我们只需要一个异步I/O线程就能引入一个成功避开我们10年的bug,那么显然最小化同步问题是非常重要的。

也就是说,10年前实现同步的方法涉及到比我们今天所能得到的更容易出错的同步原语的使用。在Windows上,像“进入临界区”和“离开临界区”这样的操作可能真的很快,但它们也很容易出错。试图记录你是否把关键部分放在了你可能需要它们的每个地方,以及你是否记得在你进入的时候离开多少次,这些都是非常困难和容易出错的。

这个恼人的bug设法在Photoshop的同步代码中隐藏了10年,这说明并行编程是多么棘手。但它也突显出,在改善管理某些复杂问题的资源方面取得了多大进展。例如,如果Photoshop的同步在今天使用c++的基于堆栈的锁来编写,那么就不太可能会引入这样的bug。随着处理器拥有更多的核心和复杂性的增长,对新工具和更好的编程原语的需求只会加剧,以便向开发人员隐藏复杂性,并允许他们在更高的抽象级别上编码。

与此同时,软件架构师还需要关注其他一些基本问题。例如,尽管在最初的设计中使用了不太复杂的同步原语,但Photoshop团队能够从本质上忘记复杂的线程同步问题,部分原因是图像处理问题本身对并行化非常敏感。然而,Photoshop的架构也使得建立一些非常清晰的对象边界成为可能,这反过来使程序员更容易对对象进行分割,并将结果分散到多个处理器上。事实上,Photoshop的架构师敏锐地意识到并行化的最佳机会存在于何处,并相应地设计了应用程序。

概括地说,很明显,无论开发人员是否使用先进的工具和编程抽象来充分利用即将到来的多核架构,他们都需要熟练地识别出程序中那些可以从并行化中获益最多的部分。新的工具、技术和并行编程抽象可能在代码的这些部分产生最大的影响

科尔:作为操作系统设计师,我们都是在必须处理并行性的环境中成长起来的。我们为我们的操作系统提出的解决方案是否被证明是正确的并不总是很清楚。在前面的对话中,您提到了创建和删除互斥对象的经验。这些年来,我们变得更聪明了。我们已经学会了如何更高效地做事,但这并不意味着变得更容易。我们有什么锦囊妙计可以让事情变得更简单?


RUSSELL WILLIAMS:我认为在过去的20年里,我们在处理并行性的能力上取得了一些渐进式的进步,就像我们在所有其他编程方面取得了逐步的进步一样。


WILLIAMS:并行在很多方面仍然很困难。要求一个新的Photoshop滤镜来并行处理像素网格是一回事。“我将并行化并因此加快Photoshop运行JavaScript动作的方式”是另一回事。例如,我有一个JavaScript例程,它依次打开50个文件,然后对每个文件执行一组50个步骤。我不能控制那个剧本。我的工作只是让用户可以运行得更快的任何其他脚本。

我可以说,“重写你所有的脚本,这样我们就可以设计一个全新的界面,让你指定所有这些图像将被并行处理。”这是一个答案,但这需要用户和我们做很多工作。它仍然会给我们留下与并行打开图像、解析图像内容、解释JavaScript、通过应用程序框架运行关键命令对象、更新用户界面相关的问题,所有这些通常都与应用程序框架绑定在一起,因此涉及到调用一些可怕的顺序脚本解释器。一旦你开始研究阿姆达尔定律的数值,很快就会发现,试图将八种方法并行化是完全没有希望的。

另一方面,您可能会发现,例如,一种数学算法在概念上适合并行,只是因为它有一堆需要共享的数据结构。那么正确地实现数学上的并行算法有多难呢?

我认为在过去的20年里,我们在处理并行性的能力上取得了一些增量,就像我们在所有其他编程方面取得了逐步的进步一样。记得在20世纪70年代,有很多关于“软件危机”的讨论,关于软件如何变得越来越复杂,到我们无法再管理漏洞的地步。好吧,作为对这一问题的回应,在软件生产率方面并没有巨大的突破,但是我们确实从面向对象编程、改进的集成开发环境以及更好的符号调试和检查工具(用于查找内存泄漏)中获得了一些增量收益。所有这些都帮助我们逐步提高了我们的生产力,增加了我们管理复杂性的能力。

我想我们也看到了类似的情况发生在并行运算上。也就是说,尽管最早的Photoshop同步代码是按照“进入临界区,离开临界区”的方式编写的,但我们现在有了Boost线程和OpenGL等工具,它们本质上是编程语言,来帮助我们处理这些问题。如果你看看Pixel Bender(表示可以在gpu上运行的并行计算的Adobe库),你会发现它的层次要高得多,因此编写算法的人需要做的同步工作要少得多。

科尔:关键是你每次都要尝试进入一个更高的层次,这样你需要处理的细节就会越来越少。如果我们能让更多的事情自动化,我们就能变得更有效率。你还提到我们现在有比以前更好的工具。这是否意味着我们需要更好的工具来进行下一步?如果是这样,我们遗漏了什么?

WILLIAMS:调试多线程程序在所有仍然是非常困难的。调试基于gpu的编程,无论是OpenGL还是OpenCL,都还处于石器时代。在某些情况下,你运行它,你的系统出现蓝屏,然后你试着弄清楚刚才发生了什么。

科尔:这是我们所知道的。我们试图构建更强大的库,这样程序员就不必再担心很多底层的事情了。我们还创建了更好的原语库,比如开源的TBB(线程构建块)。你认为这些是开发者向供应商和研究社区寻求的东西吗?

WILLIAMS:这些东西绝对是一个巨大的帮助。我们正在仔细研究TBB。跨平台工具也是必不可少的。如果有人推出只支持Windows操作系统的产品,那对我们来说是不可能的,除非在Mac方面也有完全相同的技术。像Boost或TBB这样的跨平台工具对我们来说非常重要。


CLEM COLE:锁定你的数据结构只是真正的开始。新的调优问题将是一个真正的噩梦。


我们能在更多的图书馆层下隐藏得越多,我们的境况就越好。然而,有一件事最终限制了这些图书馆的好处,那就是阿姆达尔定律。例如,假设作为某些操作的一部分我们需要将图像变换到频域。有一个并行的FFT(快速傅里叶变换)实现,我们可以调用,也许我们甚至有一个在它之上的库来决定是否有任何意义,在发送它回来之前,将所有这些发送给GPU做一个FFT的GPU实现。但这只是我们算法中的一步。也许下一步会有一个并行库,但从FFT步骤到调用并行库的步骤将需要一些混乱。Amdahl法则就是通过这些步骤间的设置杀死你的。即使你只花10%的时间做这些事情,这也足以阻止你扩展到10个处理器以上。

尽管如此,库方法还是非常棒的,我们可以接触到的每个通用算法的并行库实现都非常受欢迎。然而,就像我们今天可以使用的许多技术一样,它在大约8到16个处理器时就开始失去动力。这并不意味着它不值得做。我们自己肯定会走库的路,因为如果要扩展到8到16个处理器,这是我们唯一可以想象的工作。

对于Photoshop开发团队的工程师来说,Amdahl定律带来的缩放限制在过去几年已经变得太熟悉了。尽管应用程序当前的并行机制已经扩展到2处理器和4处理器系统,但在具有8个或更多处理器的系统上进行的实验表明,性能改善远没有那么令人鼓舞。部分原因是随着核数的增加,处理的图像块被称为瓷砖,最终会被分割成更多的小块,从而增加了同步开销。另一个问题是,在以并行块处理图像数据的每个步骤之间,有连续的簿记步骤。正因为如此,Amdahl的定律很快就变成了Amdahl的墙。

Photoshop的工程师试图通过增加贴图的尺寸来减轻这些影响,这反过来使每个子块变大。这有助于减少同步开销,但它给开发人员带来了另一个并行计算难题:内存带宽限制。使问题更加复杂的是,在整个贴图完成之前,Photoshop不能中断像素处理操作。因此,在增加贴图大小的道路上走得太远肯定会导致延迟问题,因为应用程序将无法响应用户输入,直到它处理完整个贴图。

尽管Williams仍然相信他的团队可以在不久的将来通过使用更好的工具、库和对当前并行处理方法的增量改变来继续改善Photoshop的缩放,但最终这些技术将会失去动力。这意味着是时候开始考虑将应用程序迁移到一种完全不同的方法,包括新的并行方法和gpu的增加使用。

科尔:我认为您已经有了一些有趣的方法来分解图像处理,但是对于您的基本应用程序,您是否考虑过其他编程范式,例如MPI(消息传递接口)?

WILLIAMS:不,我们没有,因为我们一直忙于从四核世界转移到八核到十六核的世界,我们看到的是Photoshop在接下来的几年里将会被困在那个世界里。我们没有认真考虑更改消息传递样式的接口的另一个原因是,这将需要如此巨大的重新架构工作,而且我们根本不清楚在那里我们会赢什么。

科尔:我问这个问题的原因是,Intel显然希望在一个盒子里尽可能多地启用核心,而你之前提到过内存带宽的问题。这就是为什么英特尔的另一个部门对NUMA(非统一内存架构)的组合方式感兴趣的部分原因。我确信我们将会有同时具有线程部分和严重并行部分的应用程序,我们将会看到工作站内部的处理器在许多方面变得更像集群。我们可能不需要脱离芯片或开箱即用,但我们会以某种方式分解内存。我们还需要做很多其他的事情来恢复一些内存带宽,因为这将对像你这样的人产生巨大的影响。

WILLIAMS:这有很多不同的方式。很多人问我们如何处理Larrabee(英特尔MICMany集成核心架构的工程芯片)这样的东西。答案是:目前基本上没有。原因是,任何这些未来的架构,如果承诺解决某些特定的并行性问题或性能问题的某些特定部分,目前都只是一种推测。另一方面,Photoshop是一个大众市场应用程序。所以,除非我们相当确定会有数百万个这样的平台存在,否则我们不能把我们的软件架构方向押在这上面。现在,我们还没有看到桌面架构超越我们今天看到的温和且缓存一致的NUMA形式。

作为一项规则,我们避免编写大量特定于处理器或特定于制造商的代码,尽管我们进行了一些有针对性的性能调优。对我们来说,一旦我们可以使用OpenGL、OpenCL和Adobe的Pixel bender等库,或者任何利用这些库以更通用的方式访问所有GPU能力的更高级别库,生活将开始变得有趣。

我们也一直在研究Intel的Nehalem架构在这一领域所呈现的变化。在以前的所有多核cpu上,一个线程基本上可以占用所有的内存带宽。考虑到我们的许多低级操作都是内存带宽有限的,将它们线程化只会增加开销。根据我们对其他多核cpu的经验,当只有两个线程运行时,它们的带宽会受到限制,因此并行加速受到内存带宽的限制,而不是Amdahl定律或算法的本质。在Nehalem中,每个处理器核心都被限制在芯片总内存带宽的一小部分,因此即使是一个很大的memcpy也可以通过多线程来极大地提高速度。

科尔:我其实只是想做一个建筑上的陈述。请放心,您将看到尽可能多的内核,但在一定程度上,我所说的“内存带宽的保护”开始成为一个巨大的权衡;这时就必须使用其他架构技巧,从而对软件产生一些影响。问题是,如果你不能在一夜之间让所有人都更换软件,那么对于Adobe这样的公司来说,“好吧,如果我知道我将不得不处理一个盒子里的集群,我必须慢慢地开始移动我的基础,所以我将能够做到这一点”,到什么时候才会变得有经济意义?

WILLIAMS:我怀疑我们最终会看到与SMP相同的进展。也就是说,硬件和操作系统支持将被引入,这样这些平台将能够运行多个程序,或多个程序实例,而这些程序还没有被修改以利用新的体系结构。在使用SMP和GPU时,这已经被证明是正确的。将会有一小部分应用绝对依赖于能够立即利用这一全新的功能,就像视频游戏和3D渲染应用一样,他们需要尽快利用gpu。然而,大部分应用程序将不会开始显著利用新架构,直到:(1)有一个安装基础;(b)有软件支持;(c)事情的走向有明确的方向。

我认为NUMA和MPI的东西在这个节点上处于研究实验室的水平。尽管MIC芯片已经在开发过程中,但除了OpenGL和DirectX之外,我们还不清楚它的编程API是什么。

现在,我要问你一个问题:你认为在编程API和操作系统支持方面的进展如何,因为如果我们要利用这些类型的架构创新,像我这样的人将需要这些?

科尔:随着我们开发专门的硬件,无论是gpu还是网络引擎,计算机本质上正在成为处理特定任务的处理元素的联合。图像处理器在显示像素和执行某些对图像制作人员和玩家很重要的数学功能方面进行了高度调整。然后其他人出现了,他们说,“嘿,我想要能够做同样的功能。我能得到它们吗?”就在这时,像我这样的操作系统领域的工程师们开始挠头说:“是的,好吧,我想我们可以把它暴露出来。”

但我怀疑这是不是你真正想要的。我的经验是,每次我们有一个这样的特殊引擎,我们试图把它提供给全世界,你可能能够写一个应用程序库,就像你用Photoshop做的那样,可以调用一些显卡,但通常只存在几代人。也就是说,它被证明只对某一特定应用具有成本效益。所以我认为GPU将会变得越来越聪明,但它仍将继续作为一个图形引擎。这才是最划算的。

盒子的其他部分需要更通用,可能需要围绕它使用一堆专门的执行引擎,以便您能够调用和轻松利用。那么问题就来了:操作系统如何让所有这些引擎可用?

作为早期微内核开发人员之一,当我得知你们正在做的早期微内核工作时,我笑了。操作系统社区中的许多人都认为这是正确的做法。

WILLIAMS:Elxsi是一个基于消息的操作系统。它类似于独立进程的GNU Hurd,因为它通过消息进行对话。有一件事给我们带来了很大的冲击,并且今天gpu在另一个不同的环境中出现了,事实上,当我开始研究NUMAis时,我想到的第一件事就是基于消息的操作相对于你所做的其他事情来说是非常昂贵的。这也是视频应用程序遇到的问题。他们沿着这条路径做一个渲染图来表示你在视频帧上的叠加效果,然后他们会继续下去,开始渲染和合成那些东西。一旦他们在GPU上做了任何事情,他们就会把它发送到那里进行处理,然后他们就会继续工作,直到在合成堆栈图中遇到GPU无法处理的节点,这时他们就会把它吸回CPU。

他们发现,即使使用最快带宽接口上的最快带宽卡,你也只能得到一次旅行。任何超出这一范围的内容都意味着您在一开始就留在CPU上会更好。当您开始移动数据时,与之相关的带宽消耗会很快超过进行计算的成本。但GPU供应商正在不断改进这一点。

科尔:这也是我问MPI的原因之一。我现在回到这个问题,只是因为它似乎是今天的流行答案。我不是说这就是答案;它只是一种试图控制什么必须被转移、何时以及如何对数据进行分区的方法,这样你就可以编写代码来利用这些执行单元,而不必移动大量的数据。

这就是为什么Intel等公司正在探索RDMA(远程直接内存访问)等接口,这是在IB (InfiniBand)中可以找到的东西。大约一年前,英特尔收购了一家iWARP (Internet Wide Area RDMA Protocol)原始供应商,该公司还大力支持OpenFabrics联盟OFED (OpenFabrics Enterprise Distribution)的实施,所以我们现在公开的RDMA接口与以太网和IB形式的InfiniBand相同。我当然认为这种硬件将开始出现在基本CPU中,当你试图移动这些对象时就可以使用。所以你将拥有计算资源和数据移动资源,处理能力将成为所有这些东西的联合。

这意味着操作系统必须改变。我认为你是对的:届时将发生的是,应用程序将变得更加丰富,并将能够利用硬件基础中的某些部分,只要操作系统暴露它。这也是你们Adobe想要开始开发的时候,因为你们的客户已经有了内置这些功能的机器。

WILLIAMS:当我们开始研究NUMA时,我们遇到了一些可预测性的问题。理想情况下,在一个大型NUMA系统上,您希望图像平均分布在所有节点上,这样当您执行操作时,就能够启动每个CPU来处理图像的各个部分,而不必移动任何东西。

然而,实际发生的情况是,您有一个图像堆栈,有人从中进行了选择,可能从图像的中心部分选择了一些圆圈或区域,其中包含10个节点中的3个节点上的像素。为了分配用户对选择调用的计算,现在必须将这些内容复制到所有10个节点。您很快就会发现数据分散在各个地方,任何特定的选择或操作都不太可能很好地分布在NUMA节点上。然后你要花一大笔钱来重新分配,这是你开始运营的一部分。这与更普遍的带宽管理问题一起,将被证明是一个比正确锁定数据结构更困难的并行问题。

科尔:是的,在这一点上我们是完全一致的。锁定数据结构实际上只是一个开始。新的调优问题将会是您刚才描述的噩梦。

ACM队列的q戳相关文章
queue.acm.org

实际的并发性
布莱恩·坎特里尔,杰夫·邦威克
http://queue.acm.org/detail.cfm?id=1454462

约翰·轩尼诗和大卫·帕特森的对话
http://queue.acm.org/detail.cfm?id=1189286

软件和并发革命
赫伯·萨特,詹姆斯·拉鲁斯
http://queue.acm.org/detail.cfm?id=1095421

回到顶部

脚注

DOI: http://doi.acm.org/10.1145/1831407.1831423


©2010 acm 0001-0782/10/1000 $10.00

允许制作本作品的全部或部分的数字或硬拷贝用于个人或课堂使用,但前提是该拷贝不是为了盈利或商业利益而制作或分发,并且该拷贝在第一页上带有本通知和完整引用。以其他方式复制、重新发布、在服务器上发布或重新分发到列表,需要事先获得特定的许可和/或付费。

数字图书馆是由计算机协会出版的。版权所有©2010 ACM有限公司


没有发现记录

登录为完全访问
»忘记密码? *创建ACM Web帐户
文章内容:
Baidu
map