SHELL := bash
CFLAGS := -O3 -g
FINGERPRINT := $(shell ./shishua -b 256 2>/dev/null | ./bin/fingerprint.sh)
TARGETS := scalar sse2 ssse3 avx2 neon
SHISHUAS := shishua shishua-half \
$(addprefix shishua-,$(TARGETS)) \
$(addprefix shishua-half-,$(TARGETS))
PRNGS := shishua shishua-half chacha8 xoshiro256plusx8 xoshiro256plus romu wyrand lehmer128 rc4
# Should match header names (aside from -scalar and -ssse3)
IMPLS := $(SHISHUAS) chacha8 chacha8-avx2 chacha8-neon xoshiro256plusx8 xoshiro256plus romu wyrand lehmer128 rc4
TESTS := $(addprefix test/vectors-,$(TARGETS))
# We need second expansions.
.SECONDEXPANSION:
##
## Target rules.
##
# Replace pseudo target names with the real names.
# The HEADER preproc variable is used in prng.c.
fix_target = $(subst -scalar,,$(subst -ssse3,-sse2,$(1)))
$(IMPLS): HEADER = $(call fix_target,$@).h
# HEADERS ensures modifications on -neon.h etc. cause recompiles.
$(PRNGS): HEADERS = $(call fix_target,$@)*.h
$(TESTS): SUFFIX = $(patsubst test/vectors%,%.h,$(call fix_target,$@))
# Force SSE2, disable SSE3
%-sse2: CFLAGS += -msse2 -mno-sse3 -mno-ssse3
%-ssse3: CFLAGS += -mssse3
# -mtune=haswell disables GCC load/store splitting
%-avx2: CFLAGS += -mavx2 -mtune=haswell
# force scalar target
%-scalar: CFLAGS += -DSHISHUA_TARGET=SHISHUA_TARGET_SCALAR
ifeq ($(shell $(CC) -v 2>&1 | tail -1 | grep -o gcc),gcc)
xoshiro256plusx8: CFLAGS += -fdisable-tree-cunrolli
CFLAGS += -march=native
else
CFLAGS += -mcpu=native
endif
##
## Recipes.
##
default: shishua shishua-half
# e.g. make neon -> make shishua-neon shishua-half-neon
$(TARGETS): %: shishua-% shishua-half-%
$(IMPLS): $$(HEADER) $$(HEADERS) prng.c
$(CC) $(CFLAGS) -DHEADER='"$(HEADER)"' prng.c -o $@
intertwine: intertwine.c
$(CC) $(CFLAGS) -o $@ $<
##
## Quality testing.
##
/usr/local/bin/RNG_test:
mkdir PractRand
curl -Ls 'https://downloads.sourceforge.net/project/pracrand/PractRand-pre0.95.zip' >PractRand/PractRand.zip
cd PractRand; \
unzip PractRand.zip; \
g++ -c src/*.cpp src/RNGs/*.cpp src/RNGs/other/*.cpp -O3 -Iinclude -pthread; \
ar rcs libPractRand.a *.o; \
g++ -o RNG_test tools/RNG_test.cpp libPractRand.a -O3 -Iinclude -pthread; \
g++ -o RNG_benchmark tools/RNG_benchmark.cpp libPractRand.a -O3 -Iinclude -pthread; \
g++ -o RNG_output tools/RNG_output.cpp libPractRand.a -O3 -Iinclude -pthread
sudo mv PractRand/RNG_{test,benchmark,output} /usr/local/bin
rm -rf PractRand
/usr/local/bin/testu01: testu01.c
curl -sO 'http://simul.iro.umontreal.ca/testu01/TestU01.zip'
unzip TestU01.zip
mv TestU01-*/ testu01
cd testu01; \
./configure --prefix=/usr/local; \
make; sudo make install
rm -rf TestU01* testu01
gcc -std=c99 -Wall -O3 -o testu01 testu01.c -Iinclude -Llib -ltestu01 -lprobdist -lmylib -lm
sudo mv testu01 /usr/local/bin/
test: test/perf-$(FINGERPRINT) test/vectors test/PractRand-$(FINGERPRINT) test/BigCrush-$(FINGERPRINT)
test/vectors:
@mkdir -p test
make test/vectors-scalar
make test/vectors-sse2
make test/vectors-ssse3
make test/vectors-avx2
#make test/vectors-neon
$(TESTS): test-vectors.c test-vectors.h shishua$$(SUFFIX) shishua-half$$(SUFFIX)
$(CC) $(CFLAGS) -DHEADER='"shishua$(SUFFIX)"' -DHEADER_HALF='"shishua-half$(SUFFIX)"' $< -o $@
./$@ >> test/vectors
test/PractRand-$(FINGERPRINT): /usr/local/bin/RNG_test shishua
@mkdir -p test
@echo "Date $$(date)" | tee test/PractRand-$(FINGERPRINT)
@echo "PRNG fingerprint: $(FINGERPRINT)" | tee -a test/PractRand-$(FINGERPRINT)
./shishua | RNG_test stdin64 | tee -a test/PractRand-$(FINGERPRINT)
test/BigCrush-$(FINGERPRINT): /usr/local/bin/testu01 shishua
@mkdir -p test
@echo "Date $$(date)" | tee test/BigCrush-$(FINGERPRINT)
@echo "PRNG fingerprint: $(FINGERPRINT)" | tee -a test/BigCrush-$(FINGERPRINT)
./shishua | testu01 --big | tee -a test/BigCrush-$(FINGERPRINT)
test/benchmark-seed: $(PRNGS) intertwine
@mkdir -p test
@echo "Date $$(date)" | tee $@
for prng in $(PRNGS); do \
echo "$$prng fingerprint: $$(./$$prng | ./bin/fingerprint.sh)" | tee -a $@; \
./intertwine <(./$$prng -s 1) <(./$$prng -s 2) \
<(./$$prng -s 4) <(./$$prng -s 8) \
<(./$$prng -s 10) <(./$$prng -s 20) \
<(./$$prng -s 40) <(./$$prng -s 80) \
| RNG_test stdin -tlmax 1M -tlmin 1K -te 1 -tf 2 | tee -a $@; \
done
##
## Performance testing.
##
# This must be performed with no other processes running.
test/perf-$(FINGERPRINT): shishua
@mkdir -p test
@echo "Date $$(date)" | tee $@
@echo "PRNG fingerprint: $(FINGERPRINT)" | tee -a $@
./shishua --bytes 4294967296 -q 2>&1 | tee -a $@
test/benchmark-perf: $(PRNGS)
@mkdir -p test
@echo "Date $$(date)" | tee $@
for prng in $(PRNGS); do \
./bin/fix-cpu-freq.sh ./$$prng --bytes 10000000000 -q 2>&1 | tee -a $@; \
done
@echo | tee -a $@
@lscpu | tee -a $@
# To reach a consistent benchmark, we need a universally-reproducible system.
# GCP will do.
# Installation instructions from https://cloud.google.com/sdk/docs/downloads-apt-get
/usr/bin/gcloud:
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt-get install apt-transport-https ca-certificates gnupg
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
sudo apt-get update && sudo apt-get install google-cloud-sdk
gcloud init
# Installation instructions for Amazon Web Services CLI (for ARM servers with NEON)
# available here: https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2-linux.html
/usr/local/bin/aws:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
rm -r awscliv2.zip aws
aws configure
# Installation instructions for Scaleway CLI (for ARM servers without NEON)
# available here: https://github.com/scaleway/scaleway-cli#linux
/usr/local/bin/scw:
sudo curl -o /usr/local/bin/scw -L "https://github.com/scaleway/scaleway-cli/releases/download/v2.3.0/scw-2.3.0-linux-x86_64"
sudo chmod +x /usr/local/bin/scw
scw init
test/benchmark-perf-intel: /usr/bin/gcloud
./bin/benchmark-intel
test/benchmark-perf-amd: /usr/bin/gcloud
./bin/benchmark-amd
test/benchmark-perf-arm: /usr/local/bin/aws
./bin/benchmark-arm
test/benchmark-perf-arm-without-neon: /usr/local/bin/scw
./bin/benchmark-arm-without-neon
clean:
$(RM) -rf $(TESTS) $(IMPLS) intertwine
.PHONY: test clean