2024年Clojure调查问卷!中分享您的想法。

欢迎!有关此如何工作的更多信息,请查看关于页面。

0
Java互操作

标准的Math.random()通过声明为同步静态方法来保证线程安全。

这个补丁使用了java.util.concurrent.ThreadLocalRandom,在简单的单线程criterion.core/bench测试中,实际上比普通的Math.random()快两倍。

我研究该函数的原因是为了确保在测试多线程负载生成时的性能时,随机数生成不是瓶颈。

如果需要,当然可以根据java.util.concurrent.ThreadLocalRandom类的存在性进行条件声明(如fj-reducers),如果Clojure 1.7要与Java版本< 1.7兼容。

10 答案

0
_评论由:claj_发布

当前rand (clojure 1.6.0)的基准,$ java -version
java版本 "1.7.0_51"
OpenJDK运行环境 (IcedTea 2.4.4) (7u51-2.4.4-0ubuntu0.13.10.1)
OpenJDK 64位服务器VM (构建 24.45-b08,混合模式)

:jvm-opts ^:replace [] (即不向JVM传递任何参数)


(bench (rand 10))
评估次数:在21361228个调用中的60个样本中有1281673680次。                                                                                                                                                                                                                                                                                          
             平均执行时间:43.630075纳秒                                                                                                                                                                                                    
   执行时间标准偏差:0.420801纳秒                                                                                                                                                                                       
   执行时间下四分位数:42.823363纳秒(2.5%)                                                                                                                                                                            
   执行时间上四分位数:44.456267纳秒(97.5%)                                                                                                                                                                            
                   使用开销:3.194591纳秒                                                                                                                                                                                     
                                                                                                                                                                                                                                   
在60个样例中发现1个异常值(1.6667%)
轻度严重    1(1.6667%)
异常值的方差:1.6389%。异常值略微增加了方差

Clojure 1.7.0-master-SNAPSHOT.

(bench (rand 10))                                                                                        
评估次数:在60个样例中,43711581次调用,共计2622694860次。                                                
        平均执行时间:20.474605纳秒                                     
    执行时间的标准差:0.248034纳秒                                                              
   执行时间的下四分位数:20.129894纳秒(2.5%)                                                      
   执行时间的上四分位数:21.009303纳秒(97.5%)                                                      
                   开销使用:2.827337纳秒                                                                
                                                                                                              
在60个样例中发现2个异常值(3.3333%)
        轻度严重    2(3.3333%)
异常值的方差:1.6389%。异常值略微增加了方差

在Clojure 1.6.0中也有类似的结果,并且进行了多次不同的测试,结果相似。java.util.Random.nextInt函数的性能出奇地差。而ThreadLocalRandom的nextInt版本性能较好,但rand-int可以取负整数,这会导致对于(.nextInt (ThreadLocalRandom/current) n) 的某些争论转换,因为需要上下界代替简单的[0,1)随机数的乘法。

修改

参数 .nextDouble(ThreadLocalRandom/current) 非常快速,但不能处理负数。简单的乘法速度约为 30 纳秒。
0

评论者:claj

添加了一些简单的测试,以确保 rand 和 rand-int 可以接受比率、双精度浮点数以及各种类型的负数。真正的测试可能包括重复的生成测试,这些测试主要是为了了解各种参数是否有效等。

0

评论者:claj

0001-rand-using-ThreadLocalRandom-and-tests-for-random.patch 包含了修改后的 (rand) 及测试用例。

0

评论者:alexmiller

Clojure 需要 Java 1.6.0,所以将来需要重新考虑这个问题。虽然可能会发生这种情况,但我们目前没有计划在 Clojure 1.7 中提高最低所需的 JDK 版本。

0

评论者:gfredericks

我一直认为,由于无法对伪随机数生成器进行初始化,因此随机性功能在总体上效用有限,而动态变量将为解决这个问题提供合理的方式。

也许可以通过标准库部分解决这两个问题?我在 https://github.com/fredericksgary/four 上开始了一个,但可能 contrib 库更容易使大家标准化。

0

评论者:claj

Gary,我非常支持创建一个精心设计的随机库,这可能是 clojure.core.random 的一个候选库,如果这会有所帮助的话。

请参阅 http://code.google.com/p/javarng/,因为这似乎做了您库 four 做的事情(并更多)。我们可能可以从这个库中挽救 API、算法或两者。

我将通过邮件联系您!

0
by

评论者:gfredericks

回想起来,clojure.core 中的 rand 变量不应该引起破坏性的变化,所以我将为此创建一个工单以观察进展。这至少可以解决使用 {{binding}} 的并发问题。我能想到的唯一反对意见是动态变量的性能问题吗?

0
by

评论者:gfredericks

新问题在 CLJ-1452。

0
by

评论者:jafingerhut

2014年5月11日发布的补丁 0001-rand-using-ThreadLocalRandom-and-tests-for-random.patch 在2014年8月29日对 Clojure 进行了一些提交后,不再干净地应用到最新的 master 中。在那一天之前,它应用得很好。

我还没有检查更新这个补丁可能有多容易或有多困难。有关更新补丁的技巧,请参阅本页面的“更新旧补丁”部分:http://dev.clojure.org/display/community/Developing Patches

0
by
参考:[连接到 CLJ-1420](https://clojure.atlassian.net/browse/CLJ-1420)(由 claj 报告)
...