Skip to content

Commit

Permalink
Merge 0ea3eb0 into c4715e6
Browse files Browse the repository at this point in the history
  • Loading branch information
smarr committed Aug 8, 2020
2 parents c4715e6 + 0ea3eb0 commit c32afc2
Show file tree
Hide file tree
Showing 5 changed files with 534 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .gitlab-ci.yml
Expand Up @@ -63,14 +63,15 @@ benchmark_job:
- ant compile
- rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns

benchmark_csp_and_interp_job:
benchmark_job_others:
stage: benchmark
tags: [benchmarks, infinity]
allow_failure: true
script:
- ant compile
- rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns-SavinaCSP
- rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns-interp
- rebench --experiment="CI Benchmark Run Pipeline ID $CI_PIPELINE_ID" --branch="$CI_COMMIT_REF_NAME" -c codespeed.conf SOMns-Mutex

benchmark_nightly_job:
stage: benchmark
Expand Down
30 changes: 28 additions & 2 deletions codespeed.conf
Expand Up @@ -60,13 +60,13 @@ benchmark_suites:
extra_args: "1 0 4"
codespeed_name: "1st.Lee"
- LeeSTM:
extra_args: "1 0 4"
extra_args: "1 0 1"
codespeed_name: "1st.LeeSTM"
- Vacation:
extra_args: "1 0 8"
codespeed_name: "1st.Vacation"
- VacationSTM:
extra_args: "1 0 8"
extra_args: "1 0 1"
codespeed_name: "1st.VacationSTM"
- Splay:
extra_args: "1 0 1"
Expand Down Expand Up @@ -594,6 +594,22 @@ benchmark_suites:
extra_args: "700 4"
codespeed_name: "CSP.Philosophers"

mutex:
description: various mutex based benchmarks
gauge_adapter: RebenchLog
command: &MUTEX_CMD " core-lib/Benchmarks/Harness.ns MutexSuite.%(benchmark)s 50 0"
max_invocation_time: 500
warmup: 30
benchmarks:
- ProducerConsumer:
#buffersize numThreads, split threads equally into producers and consumers
extra_args: "4000 4"
codespeed_name: "Mutex.ProducerConsumer"
- Philosophers:
#numrounds numThreads, uses numThreads - 1 Philosophers
extra_args: "500 4"
codespeed_name: "Mutex.Philosophers"

# VMs have a name and are specified by a path and the binary to be executed
executors:
SOMns-interp:
Expand Down Expand Up @@ -703,6 +719,16 @@ experiments:
suites:
- savina-csp

SOMns-Mutex:
description: Run mutex benchmarks
executions:
- SOMns-interp-tn:
suites:
- mutex
- SOMns-graal-tn:
suites:
- mutex

SOMns-interp:
description: All benchmarks on SOMns without Graal
suites:
Expand Down
261 changes: 261 additions & 0 deletions core-lib/Benchmarks/MutexSuite.ns
@@ -0,0 +1,261 @@
class MutexSuite usingPlatform: platform andHarness: harness = Value (
| private Benchmark = harness Benchmark.
private processes = platform processes.
private Channel = processes Channel.
private Process = processes Process.
private Array = platform kernel Array.
private Condition = platform threading Condition.
private Delay = platform threading Delay.
private Mutex = platform threading Mutex.
private Thread = platform threading Thread.
|)(
(* A simple PRNG, to be as portable as possible. *)
public class Random new: seed = (
| private seed ::= seed.
private gotNextGaussian ::= false.
private nextNextGaussian ::= 0.0. |
) (
public next = (
seed:: ((seed * 1309) + 13849) & 65535.
^ seed
)

(* Returns an integer within the range of [0, bound) *)
public next: bound = (
^ next % bound
)

(* Returns a double uniformly distributed in the range of [0.0, 1.0) *)
public nextDouble = (
^ next // 65536
)

public nextBoolean = (
^ next < 32768
)

(* Returns a double normally distributed with mean 0.0
and standard deviation of 1.0 *)
public nextGaussian = (
| v1 v2 s multiplier |
gotNextGaussian ifTrue: [
gotNextGaussian:: false.
^ nextNextGaussian ].

v1:: (2.0 * nextDouble) - 1.0.
v2:: (2.0 * nextDouble) - 1.0.
s:: (v1 * v1) + (v2 * v2).

[s >= 1.0 or: [s = 0.0]] whileTrue: [
v1:: (2.0 * nextDouble) - 1.0.
v2:: (2.0 * nextDouble) - 1.0.
s:: (v1 * v1) + (v2 * v2).
].

multiplier:: (-2.0 * s log // s) sqrt.
nextNextGaussian:: v2 * multiplier.
gotNextGaussian:: true.
^ v1 * multiplier
)
) : (
public new = (
^ new: 74755
)
)

(* === Savina Microbenchmarks === *)

public class Philosophers new = Benchmark <: Value ()(

private class Arbitrator new: numPhil numRounds: numRounds = (
| private numPhil = numPhil.
private numRounds = numRounds.
private forks = Array new: numPhil withAll: false.
private numExitedPhilosophers ::= 0.
private m = Mutex new.
private m2 = Mutex new.
|)(
private hungry: leftForkId = (
| rightForkId |
rightForkId:: 1 + ((leftForkId + 1) % numPhil).

((forks at: leftForkId) or: [forks at: rightForkId])
ifTrue: [
^ false.
]
ifFalse: [
forks at: leftForkId put: true.
forks at: rightForkId put: true.
^ true ]
)

private done: leftForkId = (
| rightForkId |
rightForkId:: 1 + ((leftForkId + 1) % numPhil).

forks at: leftForkId put: false.
forks at: rightForkId put: false.
)

private exit = (
numExitedPhilosophers:: numExitedPhilosophers + 1.

numPhil = numExitedPhilosophers ifTrue: [
| forksTaken |
forksTaken:: 0.
forks do: [:f | f ifTrue: [ forksTaken:: forksTaken + 1 ] ].
forksTaken = 0 ifFalse: [
self error: 'invalid benchmark result'.
].
]
)

public benchmark = (
|philosophers|
philosophers:: Array new: numPhil.
philosophers doIndexes: [:i |
philosophers at: i put: (Thread spawn: [:id |
| roundsSoFar isEating |
roundsSoFar:: 0.
[roundsSoFar < numRounds] whileTrue: [
m critical: [
isEating:: (hungry: id).
].

isEating ifTrue: [
roundsSoFar:: roundsSoFar + 1.
m critical: [done: id].
].
].

m2 critical: [
exit.
].
] with: { i })
].

philosophers do: [:ph | ph join ].
^ true.
)
)

public innerBenchmarkLoop: numRounds numThreads: threads = (
| arbitrator |
arbitrator:: Arbitrator new: (threads - 1) numRounds: numRounds.
^ arbitrator benchmark
)
) : (
public newInstance = ( ^ self new )
public setupVerifiedRun: run = ( run problemSize )
)


public class ProducerConsumer new = Benchmark <: Value ()(
private class SynchronizedRingBuffer new: capacity = (
| buffer = Array new: capacity.
capacity = capacity.
head ::= 1. (* points to next write location *)
tail ::= 1. (* points to next read location *)
size ::= 0.
mutex = Mutex new.
waitingProducers = mutex newCondition.
waitingConsumers = mutex newCondition.
|
)(
private add: val = (
buffer at: tail put: val.
tail:: (tail % capacity) + 1.
size:: size + 1.
)

private remove = (
|result|
result:: buffer at: head.
head:: (head % capacity) + 1.
size:: size - 1.
^ result.
)

public offer: val = (
mutex critical: [
(size = capacity) ifTrue: [
(*'producer wait' println.*)
waitingProducers await.
(*'producer woke up' println.*)
].

add: val.
size > 0 ifTrue: [
waitingConsumers signalOne.
]
]
)

public poll = (
mutex critical: [
|res|
size > 0 ifFalse: [
(*'consumer wait' println.*)
waitingConsumers await.
(*'consumer woke up' println.*)
].
res:: remove.
size < capacity ifTrue:[
waitingProducers signalOne.
].
^ res
]
)
)

private busyWait: limit = (
| test |
test:: 0.
limit timesRepeat: [
test:: test + 1 ].
^ test
)

public innerBenchmarkLoop: bufferSize numThreads: threads = (
|consumers producers buffer numCycles|
consumers:: Array new: (threads / 2 ).
producers:: Array new: (threads / 2 ).
buffer:: SynchronizedRingBuffer new: bufferSize.
numCycles:: bufferSize * 10.

consumers doIndexes: [:i |
consumers at: i put: (Thread spawn: [:id |
| rand |
rand:: Random new: id * 97 .
numCycles timesRepeat: [
| rn |
rn:: rand next: 1000.
busyWait: rn.
buffer poll.
].
] with: { i })
].

producers doIndexes: [:i |
producers at: i put: (Thread spawn: [:id |
| rand |
rand:: Random new: id * 53.
numCycles timesRepeat: [
| rn |
rn:: rand next: 1000.
busyWait: rn.
buffer offer: rn.
].
] with: { i })
].

consumers do: [:ph | ph join ].
producers do: [:ph | ph join ].

^ true.
)
) : (
public newInstance = ( ^ self new )
public setupVerifiedRun: run = ( run problemSize )
)
)

0 comments on commit c32afc2

Please sign in to comment.