You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Alex D Herbert (JIRA)" <ji...@apache.org> on 2019/03/03 21:21:00 UTC

[jira] [Commented] (RNG-78) ThreadLocalRandomSource

    [ https://issues.apache.org/jira/browse/RNG-78?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16782875#comment-16782875 ] 

Alex D Herbert commented on RNG-78:
-----------------------------------

I have created an initial implementation.

The factory method does not accept arguments for the {{RandomSource}}. This is because the first call to create the random generator will fix the arguments. Subsequent calls with different arguments cannot be supported as only one generator is stored per enum value. So the simplest solution is to not support this for generators that have arguments. This is current only {{TWO_CMRES_SELECT}}.

I added a benchmark that simulates a worst case scenario for short lifetime generators. It uses JMH to run threads in parallel to create a generator and then produce numbers. I have some results for an easy to construct SPLIT_MIX and a harder to construct MWC_256. The generators were used to create {{long}} values.

For reference I have compared to {{ThreadLocalRandom}} which is an implementation of the same SplitMix64 algorithm introduced in JDK 1.7. Here are the test methods:
 * threadLocalRandom: Use {{ThreadLocalRandom.current()}}
 * threadLocalRandomWrapped: Wrap {{ThreadLocalRandom.current()}} with the {{UniformRandomProvider}} interface
 * randomSourceCreate: Create a new generator using {{RandomSource.create}}
 * threadLocalRandomSourceCurrent: Use the new {{ThreadLocalRandomSource.current()}} method

Run using 4 threads:
||numValues||randomSourceName||Method||Score||Relative||
|1|MWC_256|randomSourceCreate|26.1|5825.89|
|1|SPLIT_MIX_64|randomSourceCreate|0.798|178.13|
|1|N/A|threadLocalRandom|0.00448|1.00|
|1|N/A|threadLocalRandomWrapped|0.0045|1.00|
|1|MWC_256|threadLocalRandomSourceCurrent|0.0131|2.92|
|1|SPLIT_MIX_64|threadLocalRandomSourceCurrent|0.00977|2.18|
|10|MWC_256|randomSourceCreate|27|1467.39|
|10|SPLIT_MIX_64|randomSourceCreate|0.791|42.99|
|10|N/A|threadLocalRandom|0.0184|1.00|
|10|N/A|threadLocalRandomWrapped|0.0208|1.13|
|10|MWC_256|threadLocalRandomSourceCurrent|0.0594|3.23|
|10|SPLIT_MIX_64|threadLocalRandomSourceCurrent|0.0294|1.60|
|100|MWC_256|randomSourceCreate|26.6|170.51|
|100|SPLIT_MIX_64|randomSourceCreate|0.818|5.24|
|100|N/A|threadLocalRandom|0.156|1.00|
|100|N/A|threadLocalRandomWrapped|0.197|1.26|
|100|MWC_256|threadLocalRandomSourceCurrent|0.475|3.04|
|100|SPLIT_MIX_64|threadLocalRandomSourceCurrent|0.162|1.04|

Creating a new generator each time is slow.

ThreadLocalRandom is fastest. But then has to be wrapped if it is to be used for any class that requires a UniformRandomProvider.

Once 10 samples are required for the short lived generator the new {{ThreadLocalRandomSource}} is performing well, and once 100 samples are required then the wrapped {{ThreadLocalRandom}} is outperformed by the thread-local {{SplitMix}}.

I am not sure of the slow time for the {{MWC_256}} when used thread-locally. The user guide timings indicate that this should be about 1.5x slower than SplitMix for generation of {{long}} values. However I did not use a {{BlackHole}} to consume values and just returned the combination of all values using {{xor}}.

I will try some more generators, longer generation sequences, using a {{BlackHole}} and another machine. However I believe the new class achieves the aim of making local thread-safe short lived generators readily available.

Code can be inspected in [PR 27|https://github.com/apache/commons-rng/pull/27].

 

> ThreadLocalRandomSource
> -----------------------
>
>                 Key: RNG-78
>                 URL: https://issues.apache.org/jira/browse/RNG-78
>             Project: Commons RNG
>          Issue Type: New Feature
>          Components: simple
>    Affects Versions: 1.3
>            Reporter: Alex D Herbert
>            Assignee: Alex D Herbert
>            Priority: Minor
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> Implement a helper class that can provide thread-local {{UniformRandomProvider}} instances. 
> This can be used as an equivalent of {{ThreadLocalRandom}}:
> {code:java}
> // c.f.
> Random random = ThreadLocalRandom.current();
> // Access a thread-safe random number generator
> UniformRandomProvider rng = 
>     ThreadLocalRandomSource.current(RandomSource.SPLIT_MIX_64);
> {code}



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)