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

欢迎!请参阅关于页面了解更多有关如何使用本网站的信息。

0
Java 兼容

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

这次的补丁使用了java.util.concurrent.ThreadLocalRandom,这似乎比普通Math.random()在使用criterium.core/bench的简单单线程评判标准下快两倍。

我之所以研究这个函数,是因为要确保在多线程负载生成性能测试中随机数生成不是瓶颈。

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

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。                                                                                                                                                                                                                  l 
             平均执行时间: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。

(校验 (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)的上限和下限,而不是简单的乘法[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/,因为这似乎与你的库four做的是相同的事情(并且更多)。也许我们可以从这个库中恢复API、算法或两者。

我将通过邮件与你联系!

0
by

评论者:gfredericks

回想一下,clojure.core 中的 rand 变量不应该造成破坏性的更改,所以我会为这个问题创建一个票务以查看情况。至少,这应该可以解决与 {{binding}} 相关的并发问题。我能想到的唯一反对意见是动态变量的性能问题吗?

0
by

评论者:gfredericks

新问题在 CLJ-1452。

0
by

评论者:jafingerhut

2014年5月11日制作的补丁 patch 0001-rand-using-ThreadLocalRandom-and-tests-for-random.patch 在 Clojure 于2014年8月29日进行了某些提交后无法干净地应用到最新版本 master。在那一天之前它还能够干净地应用。

我还没有检查更新这个补丁可能容易或困难到什么程度。请参阅本页的“更新过时的补丁”部分以获取有关更新补丁的提示: http://dev.clojure.org/display/community/Developing Patches

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