diff --git a/benchmarks/dispatch.b b/benchmarks/bench-dispatch.b similarity index 100% rename from benchmarks/dispatch.b rename to benchmarks/bench-dispatch.b diff --git a/benchmarks/bench-list.b b/benchmarks/bench-list.b new file mode 100644 index 00000000..4a9c5063 --- /dev/null +++ b/benchmarks/bench-list.b @@ -0,0 +1,75 @@ +# This code is derived from the SOM benchmarks +# +# Based on the JavaScript implementation at +# https://github.com/smarr/are-we-fast-yet/blob/master/benchmarks/JavaScript/list.js + +class Element { + Element(v){ + self.val = v + self.next = nil + } + + length() { + if self.next == nil { + return 1 + } + + return 1 + self.next.length() + } +} + +class List { + benchmark() { + var result = self.tail( + self.make_list(15), + self.make_list(10), + self.make_list(6) + ) + + return result.length() + } + + make_list(length) { + if length == 0 { + return nil + } + + var e = Element(length) + e.next = self.make_list(length - 1) + return e + } + + is_shorter_than(x, y) { + var x_tail = x + var y_tail = y + + while y_tail != nil { + if x_tail == nil { + return true + } + + x_tail = x_tail.next + y_tail = y_tail.next + } + + return false + } + + tail(x, y, z) { + if self.is_shorter_than(y, x) { + return self.tail( + self.tail(x.next, y, z), + self.tail(y.next, z, x), + self.tail(z.next, x, y) + ) + } + + return z + } +} + +var start = microtime() +echo List().benchmark() == 10 +var end = microtime() + +echo 'Time taken = ${(end - start) / 1000000} seconds' \ No newline at end of file diff --git a/benchmarks/bench-sieve.b b/benchmarks/bench-sieve.b index 772dea13..233aa20d 100644 --- a/benchmarks/bench-sieve.b +++ b/benchmarks/bench-sieve.b @@ -1,4 +1,4 @@ -# The sieve benchmark counts the number of primes below 600000. +# The sieve benchmark counts the number of primes below 600000 based on the sieve of Eratosthenes. # The correct result is 49098. # # based on the JavaScript implementation at diff --git a/benchmarks/bench-spectral-norm-2.b b/benchmarks/bench-spectral-norm-2.b new file mode 100644 index 00000000..a937cf7f --- /dev/null +++ b/benchmarks/bench-spectral-norm-2.b @@ -0,0 +1,101 @@ +/** + * The Computer Language Benchmarks Game + * https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ + * + * contributed by Richard Ore + * based on contributed work by Ziad Hatahet + * based on the Go entry by K P anonymous + * + * This implementation of the spectral norm employs multithreading + * to achieve more than 10x the speed over the ordinary version + * (depending on how many cores your cpu has). + */ + +import thread + +def spectralnorm(n) { + if !n n = 100 + + var u = [1] * n + var v = [0] * n + + for i in 0..10 { + a_times_transp(v, u) + a_times_transp(u, v) + } + + var vbv = 0, vv = 0 + for i in 0..n { + var vi = v[i] + vbv += u[i] * vi + vv += vi ** 2 + } + + return ((vbv / vv) ** 0.5) +} + +def a_times_transp(v, u) { + var x = [0] * u.length() + var t = [] + var ncpu = thread.cpu_count + + for i in 0..ncpu { + t.append(thread.start( + times, + [ + x, + i * v.length() / ncpu, + (i + 1) * v.length() / ncpu, + u, + false, + ] + )) + } + + for i in 0..ncpu { + t[i].await() + } + + for i in 0..ncpu { + t[i] = thread.start( + times, + [ + v, + i * v.length() / ncpu, + (i + 1) * v.length() / ncpu, + x, + true, + ] + ) + } + + for i in 0..ncpu { + t[i].await() + } +} + +def times(_, v, ii, n, u, transpose) { + var ul = u.length() + for i in ii..n { + var vi = 0 + for j in 0..ul { + if transpose { + vi += u[j] / a(j, i) + } else { + vi += u[j] / a (i, j) + } + } + + v[i] = vi + } +} + +def a(i, j) { + return (i + j) * (i + j + 1) / 2 + i + 1 +} + +var start = microtime() +echo spectralnorm(5500) +var end = microtime() + +echo '\nTime taken = ${(end - start) / 1000000} seconds' diff --git a/benchmarks/bench-spectral-norm.b b/benchmarks/bench-spectral-norm.b index 8ad9547e..bb0f7638 100644 --- a/benchmarks/bench-spectral-norm.b +++ b/benchmarks/bench-spectral-norm.b @@ -1,15 +1,16 @@ /** * The Computer Language Benchmarks Game * https://salsa.debian.org/benchmarksgame-team/benchmarksgame/ - * contributed by Ian Osgood + * + * contributed by Richard Ore + * based on contributed work by Ian Osgood * modified for Node.js by Isaac Gouy - * modified for Blade by Ore Richard */ def A(i, j) { - return 1 /( - (i + j) * (i + j + 1 ) / 2 + i + 1 - ) + return 1 / ( + (i + j) * (i + j + 1 ) / 2 + i + 1 + ) } def Au(u, v) { @@ -37,7 +38,7 @@ def AtAu(u, v, w) { def spectralnorm(n) { var i, u = [0] * n, v = [0] * n, - w = [0] * n, vv = 0, vBv = 0 + w = [0] * n, vv = 0, vBv = 0 for i in 0..n { u[i] = 1 diff --git a/libs/thread.b b/libs/thread.b index eccaac70..7045c183 100644 --- a/libs/thread.b +++ b/libs/thread.b @@ -91,19 +91,27 @@ */ import _thread +import _process import reflect import os + var _MIN_STACK_SIZE = 16384 # 16kb var _DEFAULT_STACK_SIZE = 65536 # 64kb - var _main_thread_id = _thread.get_id() def _is_not_main_thread(id) {id return id != _main_thread_id } + +/** + * The number of CPU cores available on the current device. + * @type number + */ +var cpu_count = _process.cpu_count + /** * The thread class exposes methods to manage creating, running, * and controlling threads.