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))                                                                                                                                        
评估次数: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))                                                                          
评估次数:2622694860次,在60个样本中的43711581次调用中进行。
        平均执行时间: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)。

变更

使用 `(ThreadLocalRandom/current) .nextDouble` 的参数非常快,但不能处理负参数。直接乘以随机数得到的速度大约是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

加里,我非常支持创建一个深思熟虑的随机库,这可能是一些库 clojure.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 报告)
...