[ 
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)

Reply via email to