【问题标题】:Multi-Core and Concurrency - Languages, Libraries and Development Techniques [closed]多核和并发 - 语言、库和开发技术 [关闭]
【发布时间】:2010-09-12 09:49:05
【问题描述】:

CPU 架构格局发生了变化,多核是一种趋势,它将改变我们开发软件的方式。我用 C、C++ 和 Java 做过多线程开发,我用各种 IPC 机制做过多进程开发。对于开发人员来说,使用线程的传统方法似乎并不容易使用支持高度并发的硬件。

您知道哪些语言、库和开发技术有助于缓解创建并发应用程序的传统挑战?我显然在考虑死锁和竞争条件等问题。设计技术、库、工具等也很有趣,它们有助于实际利用并确保可用资源得到利用——仅仅编写一个安全、强大的线程应用程序并不能确保它使用所有可用的内核。

到目前为止我看到的是:

  • Erlang:基于进程,消息传递 IPC,'actor 的并发模型
  • Dramatis:用于 Ruby 和 Python 的演员模型库
  • Scala:用于 JVM 的函数式编程语言,增加了一些并发支持
  • Clojure:用于 JVM 的函数式编程语言,带有演员库
  • Termite: Erlang 进程方法和消息传递给 Scheme 的端口

您还知道哪些内容,哪些内容对您有用,您认为哪些内容值得一看?

【问题讨论】:

  • 您将并发性和并行性混为一谈。
  • 我认为说 Clojure 有一个“演员库”有点不准确——事实上,整个语言都是围绕并发和不变性设计的。值得一看 infoq.com/presentations/Value-Identity-State-Rich-Hickey 以了解更多哲学。
  • +1 mikera....Clojure 支持代理,而不是演员。使用 Actor,您可以将数据发送到一个实体,以告诉该实体对其他一些数据进行变异。使用代理,您可以向实体发送函数以改变该实体的状态。

标签: programming-languages concurrency functional-programming multicore


【解决方案1】:

What parallel programming model do you recommend today to take advantage of the manycore processors of tomorrow? 的问题已经被问过了。我也在那里给出了以下答案。

Kamaelia 是一个 python 框架,用于构建具有大量通信进程的应用程序。

Kamaelia - 并发变得有用、有趣

在 Kamaelia 中,您可以使用相互通信的简单组件构建系统。这加快了开发速度,极大地帮助了维护,还意味着您构建自然并发软件。它旨在供任何开发人员(包括新手)访问。这也让它变得有趣:)

什么样的系统?网络服务器、客户端、桌面应用程序、基于 pygame 的游戏、转码系统和管道、数字电视系统、垃圾邮件根除器、教学工具等等:)

这是来自 Pycon 2009 的视频。首先将 Kamaelia 与 Twisted 和 Parallel Python 进行比较,然后动手演示 Kamaelia。

Easy Concurrency with Kamaelia - Part 1 (59:08)
Easy Concurrency with Kamaelia - Part 2 (18:15)

【讨论】:

    【解决方案2】:
    【解决方案3】:

    multiprocessing 是一个简化多核编程的 python 库,正如另一个答案中提到的那样。

    使用 python 的multiprocessing 编写的程序可以很容易地进行修改,以将工作交付到云端,而不是本地核心。 piCloud 利用这一点在云上提供强大的按需处理能力:您只需修改 2 行代码。

    因此,要点如下:在为多核选择库时,人们可能想问一下云方法是否也有意义。

    【讨论】:

      【解决方案4】:

      我已经在 Ada 中进行并发编程近 20 年了。

      语言本身(不是一些附加在库中的)支持线程(“任务”)、多种调度模型和多种同步范例。您甚至可以使用内置原语构建自己的同步方案。

      您可以将 Ada 的 rendezvous 视为一种面向过程的同步工具,而 protected objects 则更面向对象。 Rendezvous 类似于 monitors 的旧 CS 概念,但功能更强大。受保护对象是具有同步原语的特殊类型,允许您构建与操作系统锁、信号量、事件等完全相同的东西。但是,它足够强大,您还可以根据您的确切需求发明和创建自己类型的同步对象.

      【讨论】:

        【解决方案5】:

        C++0x 将提供std::lock 函数用于将多个互斥锁锁定在一起。这将有助于缓解由于乱序锁定导致的死锁。此外,C++0x 线程库将包含 promise、futures 和打包任务,它们允许线程等待在另一个线程上执行的操作的结果,而无需任何用户级锁。

        【讨论】:

          【解决方案6】:

          OpenMP.

          它为您处理线程,因此您只需担心要并行运行 C++ 应用程序的哪些部分。

          例如。

          #pragma omp parallel for
          for (int i=0; i < SIZE; i++) 
          {
          // do something with an element
          }
          

          上面的代码将在你告诉 openmp 运行时使用的尽可能多的线程上运行 for 循环,所以如果 SIZE 为 100,并且你有一个四核盒子,那么 for 循环将在每个线程上运行 25 个项目核心。

          还有一些针对各种语言的其他并行扩展,但我最感兴趣的是在您的显卡上运行的那些。这才是真正的并行处理 :)(例如:GPU++libSh

          【讨论】:

            【解决方案7】:
            【解决方案8】:

            我建议两种范式转变:

            软件事务内存

            您可能想了解软件事务内存 (STM) 的概念。这个想法是使用乐观并发:任何与其他操作并行运行的操作都试图在一个独立的事务中完成它的工作;如果在某个时候另一个事务已提交,导致该事务正在处理的数据无效,则该事务的工作将被丢弃并再次运行。

            我认为这个想法的第一个广为人知的实现(如果不是概念验证和第一个)是 Haskell 中的那个:Papers and presentations about transactional memory in HaskellWikipedia's STM article 上列出了许多其他实现。

            事件循环和承诺

            另一种非常不同的并发处理方式是在 [E 编程语言](http://en.wikipedia.org/wiki/E_(programming_language%29).

            请注意,它处理并发的方式以及语言设计的其他部分很大程度上基于 Actor 模型。

            【讨论】:

              【解决方案9】:

              我会说:

              模型:线程 + 共享状态、actor + 消息传递、事务内存、map/reduce? 语言:Erlang、Io、Scala、Clojure、Reia 库:Retlang、Jetlang、Kilim、Cilk++、fork/join、MPI、Kamaelia、Terracotta

              我维护了一个关于此类内容(Erlang、Scala、Java 线程、actor 模型等)的并发链接博客,并且每天发布几个链接:

              http://concurrency.tumblr.com

              【讨论】:

              • 应该注意,Kamaelia 在多核支持方面并不完全。至少可以说它仍然是非常实验性的。
              【解决方案10】:

              您提到了 Java,但您只提到了线程。你看过 Java 的并发库吗?它与 Java 5 及更高版本捆绑在一起。

              这是一个非常不错的库,包含 ThreadPools、CopyOnWriteCollections 等等。查看Java Tutorial 上的文档。或者,如果您愿意,the Java docs

              【讨论】:

                【解决方案11】:

                【讨论】:

                • 这个帖子不错——发帖前搜索的时候没看到。
                • 我认为你提到的问题更具理论性,而这个问题要求现有的解决方案可以在今天而不是明天使用。只是我的 2 美分。
                【解决方案12】:

                英特尔为 C++ 提供的Threading Building Blocks 对我来说非常有趣。它提供了比原始线程更高级别的抽象。如果您喜欢死树文档,O'Reilly 有一个非常 nice book。另请参阅Any experiences with Intel’s Threading Building Blocks?

                【讨论】:

                  【解决方案13】:

                  我在 Python 中使用了 processing。它模仿了threading 模块的API,因此非常易于使用。

                  如果您碰巧使用map/imap 或生成器/列表推导式,那么将您的代码转换为使用processing 很简单:

                  def do_something(x):
                      return x**(x*x)
                  
                  results = [do_something(n) for n in range(10000)]
                  

                  可以并行化

                  import processing
                  pool = processing.Pool(processing.cpuCount())
                  results = pool.map(do_something, range(10000))
                  

                  它将使用您必须使用的处理器来计算结果。还有惰性 (Pool.imap) 和异步变体 (Pool.map_async)。

                  有一个实现Queue.Queue的队列类,以及类似于线程的worker。

                  陷阱

                  processing 基于fork(),必须在 Windows 上进行模拟。对象通过pickle/unpickle 传输,因此您必须确保它有效。分叉一个已经获得资源的进程可能不是你想要的(想想数据库连接),但总的来说它是有效的。它运行良好,已被添加到 Python 2.6 的快速通道中(参见PEP-317)。

                  【讨论】:

                  • 谢谢,这很有帮助 - 听起来想法可以与 Dramatis 分享。
                  • 最好也提一下它的后代 - 2.6 的 multiprocessing 模块。
                  【解决方案14】:

                  我正在密切关注Parallel Extensions for .NETParallel LINQ

                  【讨论】:

                    【解决方案15】:

                    我知道Reia - 一种基于 Erlang 但看起来更像 Python/Ruby 的语言。

                    【讨论】: