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

欢迎!请查看关于页面以了解更多有关此工作的信息。

0
Java互操作

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

该补丁使用了java.util.concurrent.ThreadLocalRandom,它在简单的单线程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))                                                                                                                                                                                                                                                   
评估次数:1281673680,在21361228次调用的60个样本中。                                                                                                                                                                                
             平均执行时间: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))                                                                                         
   评估次数:26,226,948,60次,在60个样本,437,115,181次调用中。
        执行时间平均值: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可以接受负整数,这会导致对(rand-int 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

我一直认为,由于无法初始化PRNG,因此在一般随机功能中效用有限,一个*}动态变量将是一个合理的做法。

也许可以通过标准库来部分解决这两个问题?我在https://github.com/fredericksgary/four上开始了一个,但大概是一个贡献库对每个人来说更容易标准化。

0

评论由:claj

Gary,我完全支持创建一个设计得很好的随机库,这可能成为clojure.core.random库的候选者,如果那会有用的话。

请查看http://code.google.com/p/javarng/,因为它似乎完成了您库四方库的功能(甚至更多)。我们可能可以从这个库中挽救either APIs,algorithms或者两者。

我将通过邮件联系你!

0
by

评论由:gfredericks

想到这一点,clojure.core中的rand变量不应该是一个破坏性的更改,所以我将为此创建一个ticket来查看它的发展。这至少应该允许解决与{{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
...