什么是Clojure的可折叠系列?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是Clojure的可折叠系列?相关的知识,希望对你有一定的参考价值。
我是Clojure的初学者,在尝试阅读有关Reducers的文章时,我发现了一种叫做折叠式收藏的东西。
他们提到矢量和地图是可折叠的集合,但不是列表。
我想了解什么是可折叠的集合,为什么矢量和地图是可折叠的?
我没有找到任何可折叠收藏的定义或解释。
答案就在文档中,如果不是很清楚的话:
另外,一些集合(持久性向量和映射)是可折叠的。减速机上的折叠操作执行并行减少...
这个想法是,使用现代硬件,可以并行地完成诸如对矢量的所有元素求和的“缩减”操作。例如,如果对400K长度向量的所有元素求和,我们可以将它们分成4组100K块,并行求和,然后将4个小计组合成最终答案。这比仅使用单个线程(单个cpu核心)快大约4倍。
Reducers生活在clojure.core.reducers
命名空间中。假设我们定义了以下别名:
( ns demo.xyz
(:require [clojure.core :as core]
[clojure.core.reducers :as r] ))
与clojure.core
相比,我们有:
core/reduce <=> r/fold ; new name for `reduce`
core/map <=> r/map ; same name for `map`
core/filter <=> r/filter ; same name for `filter`
所以,命名并不是最好的。 reduce
生活在clojure.core
命名空间中,但reduce
命名空间中没有clojure.core.reducers
。相反,在fold
中有一个名为clojure.core.reducers
的类似功能的功能。
请注意,fold
是用于组合数据列表的历史名称,与我们的求和示例一样。 See the Wikipedia entry了解更多信息。
因为折叠以非线性顺序访问数据(这对于链表来说非常低效),所以折叠仅值于对随机访问数据结构(如向量)进行。
更新#1:
如上所述,请记住“过早优化是万恶之源”的格言。以下是在8核机器上对(vec (range 1e7))
进行的一些测量,即10M条目:
(time (reduce + data))
"Elapsed time: 284.52735 msecs"
"Elapsed time: 119.310289 msecs"
"Elapsed time: 98.740421 msecs"
"Elapsed time: 100.58998 msecs"
"Elapsed time: 98.642878 msecs"
"Elapsed time: 105.021808 msecs"
"Elapsed time: 99.886083 msecs"
"Elapsed time: 98.49152 msecs"
"Elapsed time: 99.879767 msecs"
(time (r/fold + data))
"Elapsed time: 61.67537 msecs"
"Elapsed time: 56.811961 msecs"
"Elapsed time: 55.613058 msecs"
"Elapsed time: 58.359599 msecs"
"Elapsed time: 55.299767 msecs"
"Elapsed time: 62.989939 msecs"
"Elapsed time: 56.518486 msecs"
"Elapsed time: 54.218251 msecs"
"Elapsed time: 54.438623 msecs"
Criterium报道:
reduce 144 ms
r/fold 72 ms
更新#2
Rich Hickey谈到了传感器/减速器at the 2014 Clojure Conj的设计。您可能会发现这些细节很有用。基本思想是将折叠委托给每个集合类型,该集合类型使用其实现细节的知识来有效地执行折叠。
由于哈希映射在内部使用向量,因此它们可以有效地并行折叠。
盖斯·斯蒂尔(Guy Steele)的讲话比减速器早,可能只是为他们提供了灵感。 https://vimeo.com/6624203
以上是关于什么是Clojure的可折叠系列?的主要内容,如果未能解决你的问题,请参考以下文章