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

欢迎!请查看关于页面,了解更多关于这个工作原理的信息。

0
Java互操作

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

该补丁使用java.util.concurrent.ThreadLocalRandom,在简单的单线程criterium.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位服务器虚拟机(构建24.45-b08,混合模式)

:jvm-opts ^:replace [] (即不向JVM提供参数)


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

Clojure 1.7.0-master-SNAPSHOT.

(bench (rand 10))                                                                                        
评估次数:2622694860,分布在60个样本中的43711581个调用。
        平均执行时间:20.474605 ns
   执行时间标准差:0.248034 ns
   执行时间下四分位数:20.129894 ns(2.5%)
   执行时间上四分位数:21.009303 ns(97.5%)
        开销使用:2.827337 ns
                                                                                                              
在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
by

评论者:claj

添加了一些简单的测试以确保rand和rand-int接受比例、双精度和不同类型的负整数。实际测试可能包括重复的生成测试,但这些测试主要是为了确认各种参数是否起作用等。

0
by

评论者:claj

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

0
by

评论者:alexmiller

Clojure需要Java 1.6.0,所以这个问题可能需要日后再考虑。目前我们没有计划将Clojure 1.7的最低要求JDK版本提升,尽管这当然可能改变。

0
by

评论者:gfredericks

我总觉得,由于不能对PRNG进行播种,所以随机数生成器的一般功能用途有限,而一个动态变量* }可能是实现这一点的合理方式。

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

0
by

评论者:claj

Gary,我非常支持创建一个经过深思熟虑的随机库,这可能是作为cljure.core.random库的一个候选者,如果这会有所帮助。

请查看 http://code.google.com/p/javarng/,因为这个库似乎与您库的功能类似(且更多)。我们可能可以从这个库中挽救API、算法或两者都。

我会通过电子邮件联系您!

0

评论者:gfredericks

想到这一点,clojure.core中的rand变量不应该是一个破坏性变化,所以我会为此创建一个工单以查看进展情况。这至少应该能解决由{{binding}}引起的并发问题。我唯一能想到的反对意见是动态变量的性能问题吗?

0

评论者:gfredericks

新问题在CLJ-1452。

0

评论者: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
参考: https://clojure.atlassian.net/browse/CLJ-1420(由 claj 报告)
...