代码之家  ›  专栏  ›  技术社区  ›  afeldspar

任何函数语言都支持本地的分而治之吗?

  •  13
  • afeldspar  · 技术社区  · 14 年前

    很抱歉,我无法在标题中更清楚地表达这个问题,但本质上是这样的:几乎所有的函数语言都有结构,允许您通过尾部递归处理变量列表中的参数,就像在这个二郎式的伪代码中汇总了一个数字列表:

    sumup(0,A) -> A.
    sumup(N,A) -> sumup(N) + A.
    

    然而,功能语言对我的一大吸引力是它们固有的并行性。虽然一个问题,例如数字列表的求和,显然是相当可并行的,而且几乎可以肯定是由分而治之最有效地处理的,但我不知道语言特性,使这成为一种自然的编程方式。事实上,除非语言具有允许基于函数读取参数数量和基于索引检索参数的功能,否则我看不到 能够 去做吧。任何函数式语言是否具有鼓励分而治之编程的特性?

    5 回复  |  直到 14 年前
        1
  •  7
  •   Norman Ramsey    14 年前

    任何函数式语言是否具有鼓励分而治之编程的特性?

    对: 在库中创建新的高阶函数的能力。

    无论如何,列表中最重要的功能之一是 foldr 当应用于关联运算符时,原则上可以并行化,尽管在实践中很少这样做。为什么?因为 福尔德尔 是围绕顺序数据流设计的。

    功能语言的好处在于,一旦认识到这个问题,我们就可以解决这个问题,而不是通过引入新的语言特性,而是通过更加智能地使用我们已经拥有的特性。看看怎么做 Guy Steele's talk from August 2009 他解释了原因 福尔德尔 不是并行函数编程的正确库函数,他提出

    • 一种新的编程风格
    • 列表的新表示形式
    • 图书馆新的高阶函数

    这些都是为支持分而治之的编程而设计的。

    我对这次谈话感到非常兴奋的是 不需要引入新的语言特性来支持“本机”编程的分而治之。 我们可以利用已有的原语来设计更好的库。

    如果你可以访问ACM数字图书馆,你可以看到盖伊谈话的视频。 Organizing Functional Code For Parallel Execution 或者正如本·卡雷尔指出的,你可以看到 video taken by Malcom Wallace 在Vimeo上。

        2
  •  4
  •   Mauricio Scheffer    14 年前

    自动并行并不像看上去那么容易。这方面的问题是,如果分区是自动完成的,则存在过度分区(太多分区)的风险,这会增加太多的开销,或者分区不足,这不会对CPU中的所有核心进行适当的宣传。 静态地(即在编译时)弄清楚这一点是相当困难的,这就是为什么开发人员通常要对其进行注释的原因。 在哪里? 并行化。

    实例:

    哈斯克尔有 par combinator ,作为注释创建 火花 ,当一个CPU核心可用时变成一个线程的计算。

    Data Parallel Haskell :定义一个并行数组数据类型,以允许更隐式的并行化样式,但它似乎以一些限制为代价,并且仍然是实验代码。

    ( 免责声明:我不是Haskell开发者 )

    这个 Task Parallel Library in .NET 以下内容: 可以自动并行化数据,也可以实现自己的 Partitioner . 您仍然需要知道并行化是如何工作的,否则最终会 over- or underpartitioning . 里德尸体 great series of articles on the TPL and PLINQ .

    DryadLINQ 基于plinq并添加自动分布式计算。

    这些都不是语言的本土化,但它们是紧密集成的。甚至还有一个 PLINQ integration module for F# .

        3
  •  2
  •   Phil Miller    14 年前

    看看 Manticore 其前身NESL及其兄弟ZPL。所有这些语言至少都是部分功能语言,具有并行结构,可以一次对数据结构的整个内容进行操作。

        4
  •  1
  •   David Seiler    14 年前

    我不熟悉任何具有分而治之类型模式的语言。正如你所说,很难想象你是如何指定这样的东西的。

    如果没有新的符号,我认为经典函数就像 partition 是我们能做的最好的。

        5
  •  0
  •   Carl Manaster    14 年前

    这类事情在Ruby中很容易指定。在本例中,我们将一个范围分成三组,并对每个组分配一个求和方法。然后,我们对得到的部分和求和。您可以很容易地扩展它,使之成为多线程的。

    (1..10).each_slice(3).map{ |x| x.inject :+ }.inject(:+)
    

    这个例子与您的有点不同,但显示了原理。