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

欢迎!请访问关于页面获取更多关于这个网站的详细信息。

0票数
Java互操作性

标准的Math.random() 方法由于被声明为同步静态方法,因此是线程安全的。

该补丁使用java.util.concurrent.ThreadLocalRandom,实际上在criterium.core/bench的单线程基准测试中比普通的Math.random() 快两倍。

我之所以要对这个函数进行调查,是为了确保在多线程负载生成性能测试时,随机数生成不会成为瓶颈。

如果需要,可以根据class 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位服务器虚拟机 (build 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 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票数

评论者: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进行初始化,因此随机性功能在一般用途上具有局限性,而动态var是一种合理的解决办法。

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

0票数

评论者:claj

Gary,我完全支持创建一个经过深思熟虑的随机库,这可能成为clojure.core.random的候选库,如果那样做有用的话。

请查看http://code.google.com/p/javarng/,因为这个库似乎能够实现您库4的功能(并且更多)。我们可能从这个库中挽救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在某些提交后已将Clojure的最新主分支修改干净。在那之前它应用得很好。

我还没有检查更新这个补丁可能会多么容易或困难。有关更新补丁的提示,请参见本维基页面上的“更新过时的补丁”部分: http://dev.clojure.org/display/community/Developing Patches

0票数
...