Clojure 2024 状态调查!中分享您的想法。

欢迎!请参阅关于页面获取更多有关此功能的信息。

0
Clojure
将{{reduce}}应用于{{ArrayChunk}}而不是当前{{dotimes}},可以在调用时显示分块序列处理的一般改进。受影响的功能包括{{map}}、{{filter}}和{{keep}}。下表显示了相关的基准测试结果(以毫秒为单位)。括号内的数字比原始(虽然幅度小)更差。在长范围上可以看到最佳的整体改进。

*长范围*
|| f                    || before(doall)|| after(doall)|| before(chunk-last)|| after(chunk-last)||
 | {{(map inc lr)}}      | 3.75          | 2.88         | 2.15               | 2.06              |
 | {{(keep identity lr)}}| 2.56          | 2.16         | 0.75               | 0.72              |
 | {{(filter odd? lr)}}  | 2.77          | 2.20         | 1.53               | 1.45              |

*范围*
|| f                    || before(doall)|| after(doall)|| before(chunk-last)|| after(chunk-last)||
 | {{(map inc lr)}}      | 3.64          | [3.70]       | 2.32               | [2.50]            |
 | {{(keep identity lr)}}| 2.10          | 1.94         | 0.56               | 0.46              |
 | {{(filter odd? lr)}}  | 1.95          | [1.99]       | 1.19               | [1.66]            |

*向量*
|| f                    || before(doall)|| after(doall)|| before(chunk-last)|| after(chunk-last)||
 | {{(map inc lr)}}      | 3.81          | 3.68         | 2.44               | 2.15              |
 | {{(keep identity lr)}}| 2.03          | [2.16]       | 0.53               | 0.46              |
 | {{(filter odd? lr)}}  | 2.08          | [2.82]       | 1.67               | 1.39              |

*gvec*
|| f                    || before(doall)|| after(doall)|| before(chunk-last)|| after(chunk-last)||
 | {{(map inc lr)}}      | 3.69          | [3.83]       | 1.46               | 1.35              |
 | {{(保持身份 lr)}}| 2.86          | 2.82         | 2.44               | 2.52              |
 | {{(过滤奇数 lr)}}  | 2.95          | 2.70         | 2.08               | 2.07              |

所有基准测试都在新启动的 JVM 上执行,丢弃具有大离群值差异的结果。使用的通用基准模板形式为:{{(let [xs chunked-seq] (bench (doall (f xs))))}} 其中

* "chunked-seq" 是下列之一:{{(range 100000)}}, {{(range 1e5)}}, {{(vec (range 1e5))}} 或 {{(into (vector-of :int) (range 1e5))}}
* "doall" 可以是 {{doall}} 或 {{chunk-last}}(以下将定义)
* "f" 是下列之一:{{(map inc xs)}}, {{(filter odd? xs)}} 或 {{(keep identity xs)}}.

观察结果

* 块越多、块越大,效果越显著。与 32 大于的块的大块(chunked)序列可以额外从这些变化中获益。
同样的变更使 {{keep-indexed}} 和 {{map-indexed}} 变得更糟,因此未对其进行更改。
{{for}} 宏也具备块感知的特性,但它使用显式循环来处理 {{:let, :when, :while}} 情况,这与块缓冲区更改难以区分。
{{chunk-last}} 是一个块感知的函数,用于通过块访问最后一个元素。与逐个遍历序列的 {{doall}} 相比,{{chunk-last}} 在执行前和执行后的代码更改方面都更高效。函数定义如下:{{(defn chunk-last [xs] (when-let [xs (seq xs)] (if-let [cn (chunk-next xs)] (recur cn) (last xs))))}}
在定义 {{map}} 之前,将 {{dotimes}} 的初始临时预定义从核心中移除。这包含在补丁中。

8 答案

0

由 alexmiller 发表的评论:

你能把补丁压扁吗?

0

由 reborg 发表的评论:

当然可以。

0

由 alexmiller 发表的评论:

谢谢!

0

由 reborg 发表的评论:

在CLJ-2346-2.patch中新增:在看到速度略有提升后,将Interop调用中的{{.count}}更改为正常的{{count}}。更新了表格以反映新的基准数据。

0

由 alexmiller 发表的评论:

使用.reduce与reduce有什么不同?

0

由 reborg 发表的评论:

因为这是对IChunk的操作,而这个操作没有通过正常的coll-reduce暴露出来。

0

由 alexmiller 发表的评论:

如果IChunk扩展了IReduceInit,就可以实现。

0
参考:[https://clojure.atlassian.net/browse/CLJ-2346](https://clojure.atlassian.net/browse/CLJ-2346)(由reborg报告)
...