Skip to content

Commit

Permalink
Added experiments (#142)
Browse files Browse the repository at this point in the history
* timing experiment Java 17+

* Update pom.xml

* updated benchmarks

* Update TimeZigguratVersusJavaBuiltin.java

* change benchmark mode, etc

* Create results.txt

* moved directories

* update experiments

* renamed directory

* data from runs of new version

* deternine which gaussian alg for all PRNGs

* Create README.md

* Create README.md

* Create README.md

* Update README.md

* Update README.md

* Update README.md
  • Loading branch information
cicirello authored May 29, 2024
1 parent aa6bb3a commit ca46561
Show file tree
Hide file tree
Showing 11 changed files with 1,051 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
target/
dependency-reduced-pom.xml
31 changes: 27 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[<img alt="Ziggurat Gaussian - Fast Gaussian distributed pseudorandom number generation in Java via the Ziggurat algorithm"
src="https://raw.githubusercontent.com/cicirello/ZigguratGaussian/master/images/ziggurat-gaussian.png" width="640">](#ziggurat-gaussian)

Copyright (C) 2015, 2017-2023 [Vincent A. Cicirello](https://www.cicirello.org/).
Copyright (C) 2015, 2017-2024 [Vincent A. Cicirello](https://www.cicirello.org/).

| __Packages and Releases__ | [![Maven Central](https://img.shields.io/maven-central/v/org.cicirello/ziggurat.svg?label=Maven%20Central&logo=apachemaven)](https://central.sonatype.com/artifact/org.cicirello/ziggurat/) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/cicirello/ZigguratGaussian?logo=GitHub)](https://github.com/cicirello/ZigguratGaussian/releases) |
| :--- | :--- |
Expand Down Expand Up @@ -35,12 +35,35 @@ Java API is the polar method (nextGaussian method of the Random and
ThreadLocalRandom classes, however the polar method is quite slow
relative to other newer available alternatives, such as the Ziggurat method.

You can find some experimental data comparing the performance of a sequential
## When to Use This Library

The following table summarizes when this library will speed up Gaussian random
number generation relative to Java's builtin functionality:

| Java Version | Significantly Faster For |
| --- | --- |
| Java 11 &le; version &lt; Java 17 | `Random`, `SecureRandom`, `SplittableRandom`,`ThreadLocalRandom` |
| Java version &ge; Java 17 | `Random`, `SecureRandom`, `ThreadLocalRandom` |

Source code and data of experiments with Java 17 can be found in
the [experiment](experiment) directory. The following paper discusses
experiments using the library with Java 17. In Java 17, several enhancements
to random number generation were introduced, including several new random number
geenrators a RandomGenerator interface, and a modified ziggurat for the new random
number generators as well as for `SplittableRandom`. The other legacy generators
still use the slow polar method, however. This report explores how and where our
ziggurat library is still relevant in Java 17.

> Vincent A. Cicirello. 2024. [Fast Gaussian Distributed Pseudorandom Number Generation in Java via the Ziggurat Algorithm](https://reports.cicirello.org/24/009/). Technical Report ALG-24-009, Cicirello.org, May 2024. [[PDF]](https://reports.cicirello.org/24/009/ALG-24-009.pdf)
You can find some additional experimental data comparing the performance of a sequential
genetic algorithm (GA) using this implementation of the Ziggurat method for
Gaussian mutation vs using the more common polar method, as well as experimental data
for the same comparison but with a PGA, in the following paper:

> V. A. Cicirello. [Impact of Random Number Generation on Parallel Genetic Algorithms](https://www.cicirello.org/publications/cicirello2018flairs.html). *Proceedings of the Thirty-First International Florida Artificial Intelligence Research Society Conference*, pages 2-7. AAAI Press, May 2018.
> V. A. Cicirello. [Impact of Random Number Generation on Parallel Genetic Algorithms](https://www.cicirello.org/publications/cicirello2018flairs.html). *Proceedings of the Thirty-First International Florida Artificial Intelligence Research Society Conference*, pages 2-7. AAAI Press, May 2018. [[PDF]](https://www.cicirello.org/publications/cicirello-flairs2018.pdf).
## Background on the Algorithm Itself

See the following articles for detailed description of the Ziggurat algorithm itself, as well as
additional experimental data:
Expand Down Expand Up @@ -83,7 +106,7 @@ the version number with the version that you want to use.
<dependency>
<groupId>org.cicirello</groupId>
<artifactId>ziggurat</artifactId>
<version>1.0.4</version>
<version>1.0.5</version>
</dependency>
```

Expand Down
20 changes: 20 additions & 0 deletions experiment/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Experiments, Sample Code, and Other Misc

This directory contains source code of experiments with the
library, sample code, and other misc items, as follows.

## Experiments with the Ziggurat Library and Java 17

The code in the directory [timing17](timing17) can be used to reproduce the experiments of the following paper, which among other things explores the relevance of the library for Java 17+:

> Vincent A. Cicirello. 2024. [Fast Gaussian Distributed Pseudorandom Number Generation in Java via the Ziggurat Algorithm](https://reports.cicirello.org/24/009/). Technical Report ALG-24-009, Cicirello.org, May 2024. [[PDF]](https://reports.cicirello.org/24/009/ALG-24-009.pdf)
## Which Gaussian Algorithm Does Java Use

The code in the directory [properties](properties) extracts a list of all of the
random number generators for Java 17, and determines what implementation of
`nextGaussian` each uses. Classes that inherit the default in Java 17 use a modified
ziggurat, which is faster than the original ziggurat algorithm. The `Random` class,
and the classes that extend it override the default with the slow polar method. Those
are cases where our implementation of the original ziggurat algorithm is still relevant
for Java 17+ applications.
29 changes: 29 additions & 0 deletions experiment/properties/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Which Gaussian Algorithm Does Java Use

The code in this directory extracts a list of all of the random number generators
for Java 17, and determines what implementation of `nextGaussian` each uses. Classes
that inherit the default in Java 17 use a modified ziggurat, which is faster than
the original ziggurat algorithm. The `Random` class, and the classes that extend it
override the default with the slow polar method. Those are cases where our implementation
of the original ziggurat algorithm is still relevant for Java 17+ applications.

## Building with Maven

To compile, execute the following within this directory:

```Shell
mvn clean package
```

## Running

To run, execute the following within this directory:

```Shell
java -cp target/what-gaussian-1.0.0.jar org.cicirello.experiments.whatgaussian.WhatGaussian
```

## Output

If you just want to inspect the output from my run, see the
file [what-gaussian-implementation.txt](what-gaussian-implementation.txt).
175 changes: 175 additions & 0 deletions experiment/properties/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.cicirello</groupId>
<artifactId>what-gaussian</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>

<name>Check which RandomGenerators use default Gaussian algorithm.</name>

<description>Determines which of Java's builtin pseudorandom number generators
use the RandomGenerator interface's default algorithm for nextGaussian, which
override it.
</description>

<url>https://github.com/cicirello/ZigguratGaussian</url>

<licenses>
<license>
<name>GPL-3.0-or-later</name>
<url>https://www.gnu.org/licenses/gpl-3.0.en.html</url>
<distribution>repo</distribution>
<comments>
Check which RandomGenerators use default Gaussian algorithm.
Copyright (C) 2024 Vincent A. Cicirello.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
</comments>
</license>
</licenses>

<developers>
<developer>
<name>Vincent A Cicirello</name>
<email>development@cicirello.org</email>
<url>https://www.cicirello.org/</url>
<organization>Cicirello.org</organization>
<organizationUrl>https://www.cicirello.org/</organizationUrl>
</developer>
</developers>

<organization>
<name>Cicirello.org</name>
<url>https://www.cicirello.org/</url>
</organization>

<profiles>
<profile>
<id>analysis</id>
<build>
<plugins>
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.1.0</version>
<configuration>
<htmlOutput>true</htmlOutput>
<excludeFilterFile>${session.executionRootDirectory}/spotbugs-exclude.xml</excludeFilterFile>
<plugins>
<plugin>
<groupId>com.h3xstream.findsecbugs</groupId>
<artifactId>findsecbugs-plugin</artifactId>
<version>1.12.0</version>
</plugin>
</plugins>
</configuration>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>spotbugs</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<issueManagement>
<system>github</system>
<url>https://github.com/cicirello/ZigguratGaussian/issues</url>
</issueManagement>

<dependencies>
<dependency>
<groupId>org.cicirello</groupId>
<artifactId>ziggurat</artifactId>
<version>1.0.5</version>
</dependency>
</dependencies>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
<maven.javadoc.skip>true</maven.javadoc.skip>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.2</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<failOnWarnings>false</failOnWarnings>
<failOnError>true</failOnError>
<windowtitle>Check which RandomGenerators use default Gaussian algorithm</windowtitle>
<doctitle>Check which RandomGenerators use default Gaussian algorithm</doctitle>
<author>true</author>
<version>false</version>
<nosince>true</nosince>
<notimestamp>true</notimestamp>
<bottom><![CDATA[Copyright &copy; 2024 <a href=\"https://www.cicirello.org/\" target=_top>Vincent A. Cicirello</a>. All rights reserved.]]></bottom>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify.fmt</groupId>
<artifactId>fmt-maven-plugin</artifactId>
<version>2.21.1</version>
<executions>
<execution>
<goals>
<goal>format</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Check which RandomGenerators use default Gaussian algorithm.
* Copyright (C) 2024 Vincent A. Cicirello
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package org.cicirello.experiments.whatgaussian;

import java.util.concurrent.ThreadLocalRandom;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;

/**
* Determines which of Java's builtin pseudorandom number generators use the RandomGenerator
* interface's default algorithm for nextGaussian, which override it.
*
* @author <a href=https://www.cicirello.org/ target=_top>Vincent A. Cicirello</a>, <a
* href=https://www.cicirello.org/ target=_top>https://www.cicirello.org/</a>
*/
public final class WhatGaussian {

/**
* Entrypoint for program.
*
* @param args unused
*/
public static void main(String[] args) {

System.out.printf("%10s %21s %s\n", "Group", "RandomGenerator", "Where nextGaussian declared");
RandomGeneratorFactory.all()
.sorted((f1, f2) -> f1.group().compareTo(f2.group()))
.forEach(
generatorFactory -> {
String name = generatorFactory.name();
String group = generatorFactory.group();
RandomGenerator r = generatorFactory.create();
try {
String classThatDeclaresNextGaussian =
r.getClass().getMethod("nextGaussian").getDeclaringClass().getName();
System.out.printf("%10s %21s %s\n", group, name, classThatDeclaresNextGaussian);
} catch (NoSuchMethodException exception) {
System.out.println(
"Something highly unexpexpected occured. A method with a default not found.");
}
});
try {
String classThatDeclaresNextGaussian =
ThreadLocalRandom.current()
.getClass()
.getMethod("nextGaussian")
.getDeclaringClass()
.getName();
System.out.printf(
"%10s %21s %s\n", "Legacy", "ThreadLocalRandom", classThatDeclaresNextGaussian);
} catch (NoSuchMethodException exception) {
System.out.println(
"Something highly unexpexpected occured. A method with a default not found.");
}
}
}
15 changes: 15 additions & 0 deletions experiment/properties/what-gaussian-implementation.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Group RandomGenerator Where nextGaussian declared
LXM L32X64MixRandom java.util.random.RandomGenerator
LXM L128X128MixRandom java.util.random.RandomGenerator
LXM L64X128MixRandom java.util.random.RandomGenerator
LXM L128X1024MixRandom java.util.random.RandomGenerator
LXM L64X128StarStarRandom java.util.random.RandomGenerator
LXM L64X256MixRandom java.util.random.RandomGenerator
LXM L128X256MixRandom java.util.random.RandomGenerator
LXM L64X1024MixRandom java.util.random.RandomGenerator
Legacy SecureRandom java.util.Random
Legacy Random java.util.Random
Legacy SplittableRandom java.util.random.RandomGenerator
Xoroshiro Xoroshiro128PlusPlus java.util.random.RandomGenerator
Xoshiro Xoshiro256PlusPlus java.util.random.RandomGenerator
Legacy ThreadLocalRandom java.util.Random
Loading

0 comments on commit ca46561

Please sign in to comment.