Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create GitHub workflow to run benchmark suite #51

Merged
merged 46 commits into from
Mar 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
7999801
Allow querying arbitrary languages in versions.sh
MilesCranmer Feb 18, 2022
be74ccf
Modify Makefile to only run some languages for GH actions
MilesCranmer Feb 18, 2022
4a234c2
Create draft workflow for running benchmarks
MilesCranmer Feb 18, 2022
046ad04
Add sudo
MilesCranmer Feb 18, 2022
287df3e
Add missing sudo for fortran
MilesCranmer Feb 18, 2022
b762cf6
Fix numpy install
MilesCranmer Feb 18, 2022
4fa9d4a
Attempt to fix JULIAHOME
MilesCranmer Feb 18, 2022
5fe7434
Fix JULIAHOME
MilesCranmer Feb 18, 2022
6d13d88
Make action build julia from source
MilesCranmer Feb 18, 2022
d6b6721
Add go to github workflow
MilesCranmer Feb 18, 2022
b3f0c13
Fix Julia build caching
MilesCranmer Feb 18, 2022
de58980
Fix spaces in BLASDIR
MilesCranmer Feb 18, 2022
2b6a3d4
Run empty benchmark to cache Julia build
MilesCranmer Feb 18, 2022
72b7d44
Turn back on benchmark
MilesCranmer Feb 18, 2022
90c55e8
Fix syntax error in BLASDIR
MilesCranmer Feb 18, 2022
6b5da95
Allow variable number of iterations in tests
MilesCranmer Feb 18, 2022
e161813
cut first part of openblas manifest
MilesCranmer Feb 18, 2022
be3ae82
Find openblas library
MilesCranmer Feb 19, 2022
80ee2d9
Fix BLAS linking
MilesCranmer Feb 19, 2022
0ccc6c8
Force user to set up dSFMT
MilesCranmer Feb 19, 2022
89fc84a
Fix blas dir on GitHub actions
MilesCranmer Feb 19, 2022
2055303
Unpack blas manually
MilesCranmer Feb 19, 2022
991eae9
Fix openblas import
MilesCranmer Feb 19, 2022
88570dd
Switch to dynamic blas library
MilesCranmer Feb 19, 2022
5002a95
Try fixing Go benchmark
MilesCranmer Feb 19, 2022
547881c
Update golang numerical package
MilesCranmer Feb 19, 2022
426f69a
Install required Compat.jl
MilesCranmer Feb 19, 2022
3a339cc
Revert golang edits and remove from GH actions
MilesCranmer Feb 19, 2022
25762d4
Add Java to github actions
MilesCranmer Feb 19, 2022
f0bfea7
Nitpick naming in workflow
MilesCranmer Feb 19, 2022
d8d07d8
Note that fortran version is unused
MilesCranmer Feb 19, 2022
18e6396
Set up javascript
MilesCranmer Feb 19, 2022
52b6a4a
Set up R lang
MilesCranmer Feb 19, 2022
46e5aad
Fix node-version argument to action
MilesCranmer Feb 19, 2022
90e171d
Add LuaJIT to github action
MilesCranmer Feb 19, 2022
df6de3e
Coarsen choice of nodejs
MilesCranmer Feb 19, 2022
ea741a0
Change luajit command
MilesCranmer Feb 19, 2022
7f3401d
Turn off lua benchmark as it is broken
MilesCranmer Feb 19, 2022
5ecbcbb
Change to using @for syntax
MilesCranmer Feb 19, 2022
10be12b
Correctly store javascript version
MilesCranmer Feb 19, 2022
e922655
Remove unnecessary apt update
MilesCranmer Feb 19, 2022
3ca28e0
Switch from comma to colon to avoid ambiguity
MilesCranmer Feb 19, 2022
99c3b08
Get github action to print csv at end
MilesCranmer Feb 19, 2022
44c6b3b
Add comment about rust version being ignored
MilesCranmer Feb 22, 2022
5084231
Apply suggestions from code review
MilesCranmer Mar 10, 2022
0ec2b43
Update .github/workflows/benchmarks.yml
MilesCranmer Mar 10, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
name: Benchmarks

on:
pull_request:
push:
branches:
- master
tags: '*'
workflow_dispatch:

concurrency:
# Skip intermediate builds: all builds except for builds on the `master` or `release-*` branches
# Cancel intermediate builds: only pull request builds
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.ref != 'refs/heads/master' || startsWith(github.ref, 'refs/heads/release-') || github.run_number }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

permissions:
contents: read

jobs:
test:
runs-on: ${{ matrix.os }}
defaults:
run:
shell: bash
strategy:
matrix:
os: [ubuntu-latest]
java-version: ['17']
julia-version: ['1.7.1']
python-version: ['3.9']
numpy-version: ['1.22']
gfortran-version: ['9'] # Note: unused since is built-in.
rust-version: ['1.42.0'] # Note: unused since controlled by `rust/rust-toolchain`
js-version: ['16']
r-version: ['4.1.2']
lua-version: ['2.0.5'] # Note: Not used as benchmark is broken.
go-version: ['1.17.4'] # Note: Not used as benchmark is broken.

steps:
- uses: actions/checkout@v3
with:
persist-credentials: false
- name: "Cache Julia"
id: cache-julia
uses: actions/cache@v2
with:
path: ~/julia
key: ${{ runner.os }}-v${{ matrix.julia-version }}
- name: "Build Julia"
if: steps.cache-julia.outputs.cache-hit != 'true'
uses: julia-actions/build-julia@v1
with:
ref: v${{ matrix.julia-version }}
- name: "Install Julia packages"
run: |
julia -e 'using Pkg; Pkg.add("Compat")'
- name: "Set up dSFMT"
run: |
cd ~/
mkdir -p dSFMT
cd dSFMT
wget https://github.com/MersenneTwister-Lab/dSFMT/archive/refs/tags/v2.2.4.tar.gz
echo "39682961ecfba621a98dbb6610b6ae2b7d6add450d4f08d8d4edd0e10abd8174 v2.2.4.tar.gz" | sha256sum --check --status
tar -xzf v2.2.4.tar.gz
mv dSFMT-*/* ./
Comment on lines +59 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to use https://github.com/JuliaBinaryWrappers/dSFMT_jll.jl/releases/download/dSFMT-v2.2.4%2B2/dSFMT.v2.2.4.x86_64-linux-gnu.tar.gz instead? This is also what's used by Julia itself, so it'd make the comparison fairer.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. Will do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I can't. This BinaryBuilder version doesn't include the C source code (dSFMT.c), which is required by the benchmark.

It says it's built by the same version though, so I think it's fine?

- name: "Set up OpenBLAS"
run: |
sudo apt-get install -y libopenblas-dev
- name: "Set up Python"
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: "Set up NumPy"
run: pip install numpy==${{ matrix.numpy-version }}
- name: "Set up Rust"
uses: actions-rs/toolchain@v1
with:
toolchain: ${{ matrix.rust-version }}
- name: "Set up Java"
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: ${{ matrix.java-version }}
cache: 'maven'
- name: "Set up JavaScript"
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.js-version }}
- name: "Set up R"
uses: r-lib/actions/setup-r@v2
with:
r-version: ${{ matrix.r-version }}
- name: "Set up LuaJit"
uses: leafo/[email protected]
with:
luaVersion: luajit-${{ matrix.lua-version }}
- name: "Set up Go"
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
- name: "Run benchmark"
run: |
JULIAHOME=~/julia DSFMTDIR=~/dSFMT/ make gh_action_benchmarks.html
- name: "Print benchmark data"
run: cat gh_action_benchmarks.csv
77 changes: 47 additions & 30 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
ifndef JULIAHOME
$(error JULIAHOME not defined. Set value to the root of the Julia source tree.)
endif
ifndef DSFMTDIR
$(error DSFMTDIR not defined. Set value to the root of the dSFMT source tree.)
endif


# Will make multi-line targets work
# (so we can use @for on the second line)
.ONESHELL:

include $(JULIAHOME)/Make.inc
include $(JULIAHOME)/deps/Versions.make

NODEJSBIN = node8
NODEJSBIN = node

ITERATIONS=$(shell seq 1 5)

#Use python2 for Python 2.x
PYTHON = python3
Expand All @@ -19,13 +30,6 @@ else
MATHEMATICABIN = math
endif

#Which BLAS library am I using?
ifeq ($(USE_SYSTEM_BLAS), 0)
BLASMANIFEST=$(shell cat $(JULIAHOME)/usr/manifest/openblas)
BLASDIR=$(JULIAHOME)/deps/scratch/$(BLASMANIFEST)/
LIBBLAS=$(BLASDIR)$(LIBBLASNAME).a
endif

FFLAGS=-fexternal-blas
#gfortran cannot multiply matrices using 64-bit external BLAS.
ifeq ($(findstring gfortran, $(FC)), gfortran)
Expand All @@ -43,25 +47,21 @@ LIBM = $(LIBMDIR)libopenlibm.a
endif
endif

DSFMTDIR = $(JULIAHOME)/deps/scratch/dsfmt-$(DSFMT_VER)
RMATHDIR = $(JULIAHOME)/deps/scratch/Rmath-julia-$(RMATH_JULIA_VER)

default: benchmarks.html

export OMP_NUM_THREADS=1
export GOTO_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1

perf.h: $(JULIAHOME)/deps/Versions.make
echo '#include "$(BLASDIR)cblas.h"' > $@
echo '#include "cblas.h"' > $@
echo '#include "$(DSFMTDIR)/dSFMT.c"' >> $@

bin/perf%: perf.c perf.h
$(CC) -std=c99 -O$* $< -o $@ -I$(DSFMTDIR) $(LIBBLAS) -L$(LIBMDIR) $(LIBM) $(CFLAGS) -lpthread
$(CC) -std=c99 -O$* $< -o $@ -I$(DSFMTDIR) -lopenblas -L$(LIBMDIR) $(LIBM) $(CFLAGS) -lpthread

bin/fperf%: perf.f90
mkdir -p mods/$@ #Modules for each binary go in separate directories
# $(FC) $(FFLAGS) -Jmods/$@ -O$* $< -o $@ $(LIBBLAS) -L$(LIBMDIR) $(LIBM) -lpthread
$(FC) $(FFLAGS) -Jmods/$@ -O$* $< -o $@ -lopenblas -L$(LIBMDIR) $(LIBM) -lpthread

benchmarks/c.csv: \
Expand All @@ -80,73 +80,90 @@ benchmarks/fortran.csv: \


benchmarks/c%.csv: bin/perf%
for t in 1 2 3 4 5; do $<; done >$@
@for t in $(ITERATIONS); do $<; done >$@

benchmarks/fortran%.csv: bin/fperf%
for t in 1 2 3 4 5; do $<; done >$@
@for t in $(ITERATIONS); do $<; done >$@

benchmarks/go.csv: export GOPATH=$(abspath gopath)
benchmarks/go.csv: perf.go
#CGO_LDFLAGS="$(LIBBLAS) $(LIBM)" go get github.com/gonum/blas/cgo
#CGO_LDFLAGS="-lopenblas $(LIBM)" go get github.com/gonum/blas/cgo
go get github.com/gonum/blas/blas64
go get github.com/gonum/blas/cgo
go get github.com/gonum/matrix/mat64
go get github.com/gonum/stat
for t in 1 2 3 4 5; do go run $<; done >$@
@for t in $(ITERATIONS); do go run $<; done >$@

benchmarks/julia.csv: perf.jl
for t in 1 2 3 4 5; do $(JULIAHOME)/usr/bin/julia $<; done >$@
@for t in $(ITERATIONS); do $(JULIAHOME)/usr/bin/julia $<; done >$@

benchmarks/python.csv: perf.py
for t in 1 2 3 4 5; do $(PYTHON) $<; done >$@
@for t in $(ITERATIONS); do $(PYTHON) $<; done >$@

benchmarks/matlab.csv: perf.m
for t in 1 2 3 4 5; do matlab -nojvm -singleCompThread -r 'perf; perf; exit' | grep ^matlab | tail -8; done >$@
@for t in $(ITERATIONS); do matlab -nojvm -singleCompThread -r 'perf; perf; exit' | grep ^matlab | tail -8; done >$@

benchmarks/octave.csv: perf.m
for t in 1 2 3 4 5; do $(OCTAVE) -q --eval perf 2>/dev/null; done >$@
@for t in $(ITERATIONS); do $(OCTAVE) -q --eval perf 2>/dev/null; done >$@

benchmarks/r.csv: perf.R
for t in 1 2 3 4 5; do cat $< | R --vanilla --slave 2>/dev/null; done >$@
@for t in $(ITERATIONS); do cat $< | R --vanilla --slave 2>/dev/null; done >$@

benchmarks/javascript.csv: perf.js
for t in 1 2 3 4 5; do $(NODEJSBIN) $<; done >$@
@for t in $(ITERATIONS); do $(NODEJSBIN) $<; done >$@

benchmarks/mathematica.csv: perf.nb
for t in 1 2 3 4 5; do $(MATHEMATICABIN) -noprompt -run "<<$<; Exit[]"; done >$@
@for t in $(ITERATIONS); do $(MATHEMATICABIN) -noprompt -run "<<$<; Exit[]"; done >$@

benchmarks/stata.csv: perf.do
for t in 1 2 3 4 5; do stata -b do $^ $@; done
@for t in $(ITERATIONS); do stata -b do $^ $@; done

benchmarks/lua.csv: perf.lua
for t in 1 2 3 4 5; do scilua $<; done >$@
@for t in $(ITERATIONS); do luajit $<; done >$@

benchmarks/java.csv: java/src/main/java/PerfBLAS.java
cd java; sh setup.sh; for t in 1 2 3 4 5; do mvn -q exec:java; done >../$@
cd java
sh setup.sh
@for t in $(ITERATIONS); do mvn -q exec:java; done >../$@

benchmarks/scala.csv: scala/src/main/scala/perf.scala scala/build.sbt
cd scala; for t in 1 2 3 4 5; do sbt run; done >../$@
cd scala
@for t in $(ITERATIONS); do sbt run; done >../$@

benchmarks/rust.csv: rust/src/main.rs rust/src/util.rs rust/Cargo.lock
cd rust; for t in 1 2 3 4 5; do cargo run --release -q; done >../$@
cd rust
@for t in $(ITERATIONS); do cargo run --release -q; done >../$@

LANGUAGES = c fortran go java javascript julia lua mathematica matlab octave python r rust
GH_ACTION_LANGUAGES = c fortran java javascript julia python r rust

# These were formerly listed in LANGUAGES, but I can't get them to run
# 2017-09-27 johnfgibson
# scala, stata

BENCHMARKS = $(foreach lang,$(LANGUAGES),benchmarks/$(lang).csv)
GH_ACTION_BENCHMARKS = $(foreach lang,$(GH_ACTION_LANGUAGES),benchmarks/$(lang).csv)

COLON_SEPARATED_GHA_LANGUAGES = $(shell echo $(GH_ACTION_LANGUAGES) | sed 's/ /:/g')

versions.csv: bin/versions.sh
$^ >$@

gh_action_versions.csv: bin/versions.sh
$^ $(COLON_SEPARATED_GHA_LANGUAGES) >$@

benchmarks.csv: bin/collect.jl $(BENCHMARKS)
@$(call PRINT_JULIA, $^ >$@)

gh_action_benchmarks.csv: bin/collect.jl $(GH_ACTION_BENCHMARKS)
@$(call PRINT_JULIA, $^ >$@)

benchmarks.html: bin/table.jl versions.csv benchmarks.csv
@$(call PRINT_JULIA, $^ >$@)

gh_action_benchmarks.html: bin/table.jl gh_action_versions.csv gh_action_benchmarks.csv
@$(call PRINT_JULIA, $^ >$@)

clean:
@rm -rf perf.h bin/perf* bin/fperf* benchmarks/*.csv benchmarks.csv mods *~ octave-core perf.log gopath/*

Expand Down
87 changes: 60 additions & 27 deletions bin/versions.sh
Original file line number Diff line number Diff line change
@@ -1,41 +1,74 @@
#!/usr/bin/env bash

echo -n "c,gcc "
gcc -v 2>&1 | grep "gcc version" | cut -f3 -d" "
# User argument declaring what languages to query:
DEFAULT_LANGUAGES="c:fortran:go:java:javascript:julia:lua:mathematica:matlab:octave:python:r:rust"
LANGUAGES=${1:-DEFAULT_LANGUAGES}

echo -n "fortran,gcc "
gfortran -v 2>&1 | grep "gcc version" | cut -f3 -d" "
LANGUAGES=":${LANGUAGES}:"

echo -n go,
go version | cut -f3 -d" "
# Check if ":c:" in languages:
if [[ $LANGUAGES == *":c:"* ]]; then
echo -n "c,gcc "
gcc -v 2>&1 | grep "gcc version" | cut -f3 -d" "
fi

echo -n java,
java -version 2>&1 |grep "version" | cut -f3 -d " " | cut -c 2-9
if [[ $LANGUAGES == *":fortran:"* ]]; then
echo -n "fortran,gcc "
gfortran -v 2>&1 | grep "gcc version" | cut -f3 -d" "
fi

echo -n "javascript,V8 "
node8 -e "console.log(process.versions.v8)"
if [[ $LANGUAGES == *":go:"* ]]; then
echo -n go,
go version | cut -f3 -d" "
fi

echo -n "julia,"
$JULIAHOME/usr/bin/julia -v | cut -f3 -d" "
if [[ $LANGUAGES == *":java:"* ]]; then
echo -n java,
java -version 2>&1 |grep "version" | cut -f3 -d " " | cut -c 2-9
fi

echo -n "lua,"
# scilua -v 2>&1 | grep Shell | cut -f3 -d" " | cut -f1 -d,
echo scilua v1.0.0-b12
if [[ $LANGUAGES == *":javascript:"* ]]; then
echo -n "javascript,V8 "
node -e "console.log(process.versions.v8)"
fi

echo -n "mathematica,"
echo quit | math -version | head -n 1 | cut -f2 -d" "
if [[ $LANGUAGES == *":julia:"* ]]; then
echo -n "julia,"
$JULIAHOME/usr/bin/julia -v | cut -f3 -d" "
fi

echo -n "matlab,R"
matlab -nodisplay -nojvm -nosplash -r "version -release, quit" | tail -n3 | head -n1 | cut -f5 -d" " | sed "s/'//g"
if [[ $LANGUAGES == *":lua:"* ]]; then
echo -n "lua,"
# scilua -v 2>&1 | grep Shell | cut -f3 -d" " | cut -f1 -d,
echo scilua v1.0.0-b12
fi

echo -n "octave,"
octave-cli -v | grep version | cut -f4 -d" "
if [[ $LANGUAGES == *":mathematica:"* ]]; then
echo -n "mathematica,"
echo quit | math -version | head -n 1 | cut -f2 -d" "
fi

echo -n "python,"
python3 -V 2>&1 | cut -f2 -d" "
if [[ $LANGUAGES == *":matlab:"* ]]; then
echo -n "matlab,R"
matlab -nodisplay -nojvm -nosplash -r "version -release, quit" | tail -n3 | head -n1 | cut -f5 -d" " | sed "s/'//g"
fi

echo -n "r,"
R --version | grep "R version" | cut -f3 -d" "
if [[ $LANGUAGES == *":octave:"* ]]; then
echo -n "octave,"
octave-cli -v | grep version | cut -f4 -d" "
fi

echo -n "rust,"
(cd rust; rustc --version | cut -c 7- | sed 's/ ([0-9a-f]* /<br>(/g')
if [[ $LANGUAGES == *":python:"* ]]; then
echo -n "python,"
python3 -V 2>&1 | cut -f2 -d" "
fi

if [[ $LANGUAGES == *":r:"* ]]; then
echo -n "r,"
R --version | grep "R version" | cut -f3 -d" "
fi

if [[ $LANGUAGES == *":rust:"* ]]; then
echo -n "rust,"
(cd rust; rustc --version | cut -c 7- | sed 's/ ([0-9a-f]* /<br>(/g')
fi