翻译:微软style的并行计算

时间:2021-11-10 00:21:41

Parallel Microsoft-Style

By Andrew Binstock, July 20, 2011

Note:主要是自动翻译,俺做了小量修改

1 Comment

The actor model of concurrency is gaining favor in Java but remains largely ignored by Microsoft

actor model已经大量使用在java中,为微软还是大量忽视了他

One area in which Microsoft operating systems have long been on the vanguard is multithreading APIs. Even before multicore processors were the norm, Microsoft offered expansive APIs for managing threads and thread-like execution streams called fibers. The Win32 platform had a wide selection of thread-management functions that could be used with considerable ease. While I can't speak for every operating system, that collection of APIs was considerably greater and more sophisticated than UNIX or Linux counterparts. Pthreads, the now-standard threading implementation on Linux, is a much smaller solution. However, Pthreads does provide a benefit singularly lacking in the Windows implementation: portability. Pthreads originated on UNIX where it still runs on the various variants. A good port on Win32 exists, in addition to the multiple Linux distributions.

Microsoft操作系统长期以来一直处于领先地位的一个领域是多线程API。 即使在多核处理器之前,微软也提供了广泛的API来管理线程和线程执行流,称为光纤。 Win32平台有很多线程管理功能,可以很容易地使用。 虽然我不能为每个操作系统说话,那个API的集合比UNIX或Linux的相当大,更复杂。 Pthreads是Linux上现在标准的线程实现,是一个更小的解决方案。 然而,Pthreads提供了一个独特的优点,而在在Windows实现中缺少的:可移植性。 Pthreads源于UNIX,它仍然运行在各种变体。 除了多个Linux发行版之外,Win32上还有一个很好的port。

The Microsoft APIs, however, are very much drawn from the traditional approach to threading, which is a complex model of creating threads, managing them individually, and using mutual exclusion to prevent them from interfering with each other. Even though Microsoft's Visual Studio IDE has decent support for working with threads, developers can expect to spend a lot of time in the debugger. In this shared-memory model, the two great debugging challenges are replicating the problem, and once it's replicated, diagnosing it.

然而,Microsoft API非常吸取传统的线程方法,线程是一个复杂的模型,它创建线程,单独管理它们,并使用互斥来防止它们相互干扰。 即使微软的Visual Studio IDE对线程的支持,开发人员可以期望在调试器中花费大量的时间。 在这种共享内存模型中,两个巨大的调试挑战是重复问题,一旦重复,诊断它。

The issue of replication has driven more than one developer to the brink of insanity, if not pushed him over the edge entirely. Some errors show up only when certain threads interact in a rare way, with each one handling a specific piece of data. This might show up as a defect report indicating that, occasionally, transactions aren't logged correctly to the database. Trying to recreate what conditions might lead to an event transiently not occurring — when dozens of threads are in various states of operation — can be exceedingly difficult, if not impossible. But even if the situation can be faithfully reproduced, trapping the condition and determining how the threads are crossing each other incorrectly is arduous. In sum, the shared-memory model is no one's idea of programming fun. And as a result, much software that should have been parallelized long ago runs serially because the job is constantly deferred until parallelization is the only way to gain the needed performance.

复制的问题已经迫使一个以上的开发者陷入精神错乱的边缘,如果不把他完全推开。 一些错误仅在某些线程以罕见的方式交互时显示,每个线程处理特定的数据片段。 这可能显示为缺陷报告,指示偶尔会将事务无法正确记录到数据库。 尝试重新创建什么条件可能导致事件暂时不发生 - 当几十个线程处于各种操作状态时 - 可能是非常困难的,如果不是不可能的话。 但是,即使情况可以忠实地再现,捕获条件和确定线程如何不正确地交叉是艰巨的。 总之,共享内存模型是没有人的编程乐趣的想法。 结果,许多应该早已并行化的软件连续运行,因为作业不断推迟,直到并行化是获得所需性能的唯一方法。

Various attempts have been made to remove this complexity and thereby facilitate parallel development. One of the strongest pushes has come from Intel, which spearheaded OpenMP a decade ago. OpenMP sought to add keywords to the C (via pragmas) and Fortran, so that portions of existing programs could be parallelized. This approach, while limited to only sections of the program, worked well. It was easy to grasp and it cleverly handled the messy thread-management issues behind the scenes. If the code ran correctly on a single thread, chances were excellent that it would still run correctly when parallelized with OpenMP keywords. Microsoft's support of OpenMP made it a natural choice for many applications.

已经进行了各种尝试来消除这种复杂性,从而有助于并行开发。 最强大的推动之一来自英特尔,这是十年前率先推动OpenMP的。 OpenMP试图向C(通过编译指示)和Fortran添加关键字,以便现有程序的一部分可以并行化。 这种方法虽然只局限于程序的一部分,但效果很好。 它很容易掌握,它巧妙地处理了幕后的线程管理问题。 如果代码在单个线程上正确运行,那么在与OpenMP关键字并行化时仍然可以正确运行的机会非常好。 Microsoft对OpenMP的支持使其成为许多应用程序的自然选择。

More recently, Intel has come out with a more elaborate solution, Cilk Plus, which follows the OpenMP model and leverages Intel's deep knowledge of threading (acquired from a decade of investment in threading tools). James Reinders of Intel provided an excellent technical overview of the problem and solution as viewed from within the industry in a recent blog post.

Java and the Actor Alternative

Interestingly, the languages on the JVM are heading towards a different kind of solution, namely actors. If you're not familiar with actors, it's easiest to think of them as functions to which discrete tasks can be sent for execution. The most common operational metaphor is a thread that has an incoming mailbox to which messages are sent by other actors. The actor processes these messages (which can include tasks to execute or data to operate on) and the output is sent to another actor for downstream work.

有趣的是,JVM上的语言正在朝着一种不同的解决方案,即actor。 如果你不熟悉actors,最容易把它们看作是离散任务可以发送执行的函数。 最常见的操作比喻是具有其他参与者发送消息的传入邮箱的线程。 actor处理这些消息(其可以包括要执行的任务或要操作的数据),并且输出被发送到另一个actor用于下游工作。

Actors avoid the dangers of the shared-memory model because they touch only the data that's sent to them in messages. If they need some external data, they request it from other actors (by sending the request in the form of a message). In addition, the data actors receive is immutable. They don't change the data, rather they copy it and transform the copy. In this way, no two threads are ever contending for access to the same data item, nor are their internal operations interfering with one another. As a result, the nightmares I described earlier disappear almost completely.

Actor避免共享内存模型的危险,因为它们只触摸在消息中发送给它们的数据。 如果他们需要一些外部数据,他们向其他参与者请求(通过以消息的形式发送请求)。 此外,数据actors接收是不可变的。 他们不更改数据,而是复制和转换副本。 这样,没有两个线程竞争访问同一数据项,它们的内部操作也不会相互干扰。 结果,我之前描述的噩梦几乎完全消失。

The actor model has been used in applications that naturally align with message passing: telephone switches, Web servers, and the like. Increasingly, however, JVM languages are using them for run-of-the-mill applications. Obviously, actors require a different kind of architecture (in most actor applications, everything is done by actors — mixed-model applications are generally not favored.). And in support of this, they are finding support in several recent languages. For example, Scala and Fantom have built in-actor libraries (Scala's enjoys native syntactic support). Groovy has a widely used actor library. And actor frameworks, such as Akka and Killim, that can be used by any JVM language have recently come to market.

演员模型已经在与消息传递自然对准的应用中使用:电话交换机,Web服务器等。 然而,越来越多的JVM语言正在将其用于运行的应用程序。 显然,演员需要不同的架构(在大多数演员应用程序中,一切都由演员完成 - 混合模型应用程序通常不受欢迎。) 为了支持这一点,他们正在寻找最近几种语言的支持。 例如,Scala和Fantom构建了一个in-actor库(Scala喜欢本地语法支持)。 Groovy有一个广泛使用的actor库。 并且可以由任何JVM语言使用的动作者框架,例如Akka和Killim最近已经上市。

For all the extensive threading APIs Microsoft offers, the company has not substantially embraced actors. A good start was made in 2010 when the Redmond giant released Asynchronous Agents Library, but this is only a partial actor implementation and it runs only in C++. (Note: A highly portable, widely used C++ library with actor building blocks — but no actor framework — is the ACE library.)

Microsoft has released a pair of packages that contain many actor primitives. These packages, named the Concurrency and Coordination Runtime (CCR) and the Decentralized Software Services (DSS), were released in 2008 as part of the Microsoft Robotics toolkit, curiously enough. The packages have languished there ever since and are not part of the .NET framework. However, some posts on Microsoft's website suggest that, at some future point, the packages will be migrated to .NET. The timing is left ambiguous and it's not clear whether the APIs will be changed in the migration, nor whether a full actor framework will be constructed from them.

Another concern about CCR and DSS is that they have not been updated for more than a year, although in the forums, a project lead from Microsoft refers at several points to an "upcoming" announcement.

In either case, there is no long history of working with this technology — nor any evidence that I can find of any other support for actors in the .NET languages. Microsoft is still primarily oriented towards the traditional models of parallel programming. The benefit of this approach is raw performance. For the same reasons, Intel's libraries target only C, C++, and Fortran — three languages that are associated with high-speed computation and frequently run as native code.

Application developers who are willing to trade a little performance for ease in writing parallel applications are likely to find Java's embrace of actors an appealing solution (although Java certainly has the traditional primitives for developers who want to follow that path.)

I expect that over time, Microsoft will increase its support for the actor programming model. But if it comes, the support will likely not be fully embraced by Redmond until pressure for large-scale actor models is applied either by its customers or competition in the market place. In the latter case, the pressure will be exerted primarily by JVM-based solutions.

对于微软提供的所有广泛的线程API,该公司没有充分接受演员。 2010年,当Redmond巨头发布了异步代理库时,这是一个好的开始,但这只是一个部分actor实现,它只能在C ++中运行。 (注意:高度可移植,广泛使用的C ++库,包含actor构建块,但没有actor框架 - 是ACE库。)

Microsoft已经发布了一对包含许多actor原语的包。这些软件包命名为并发和协调运行时(CCR)和分散软件服务(DSS),作为Microsoft Robotics工具包的一部分于2008年发布,奇怪的是。软件包从那以后就一直在努力,并且不是.NET框架的一部分。但是,微软网站上的一些帖子表明,在未来的某个时候,这些包将被迁移到.NET。时间是不明确的,并不清楚API是否将在迁移中更改,也不会从中构建完整的actor框架。

关于CCR和DSS的另一个问题是,他们没有更新一年多,尽管在论坛中,微软的一个项目从几个点提到了“即将到来”的公告。

在任何一种情况下,没有使用这种技术的悠久历史 - 也没有任何证据,我可以找到任何其他支持的.NET语言中的演员。微软仍然主要面向传统的并行编程模型。这种方法的好处是原始性能。出于同样的原因,英特尔的库仅定位C,C ++和Fortran--三种与高速计算相关的语言,并且经常作为本地代码运行。

应用程序开发人员愿意交易一点点性能以便于编写并行应用程序,可能会发现Java拥抱一个有吸引力的解决方案(尽管Java当然有传统的原语为开发者想要遵循的路径)。

我期望随着时间的推移,微软将增加对演员编程模型的支持。但是如果它来到,支持将很可能不会被雷德蒙完全拥抱,直到大型演员模型的压力由其客户或市场竞争应用。在后一种情况下,压力将主要由基于JVM的解决方案施加。

— Andrew Binstock
Editor in Chief
alb@drdobbs.com
Twitter: platypusguy