mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 09:40:21 +00:00
262 lines
5.6 KiB
Pony
262 lines
5.6 KiB
Pony
use "options"
|
|
use "time"
|
|
use "collections"
|
|
|
|
class Config
|
|
var logtable: U64 = 20
|
|
var iterate: U64 = 10000
|
|
var logchunk: U64 = 10
|
|
var logactors: U64 = 2
|
|
|
|
fun ref apply(env: Env): Bool =>
|
|
var options = Options(env)
|
|
|
|
options
|
|
.add("logtable", "l", I64Argument)
|
|
.add("iterate", "i", I64Argument)
|
|
.add("chunk", "c", I64Argument)
|
|
.add("actors", "a", I64Argument)
|
|
|
|
for option in options do
|
|
match option
|
|
| ("table", var arg: I64) => logtable = arg.u64()
|
|
| ("iterate", var arg: I64) => iterate = arg.u64()
|
|
| ("chunk", var arg: I64) => logchunk = arg.u64()
|
|
| ("actors", var arg: I64) => logactors = arg.u64()
|
|
| let err: ParseError =>
|
|
err.report(env.out)
|
|
env.out.print(
|
|
"""
|
|
gups_opt [OPTIONS]
|
|
--table N log2 of the total table size. Defaults to 20.
|
|
--iterate N number of iterations. Defaults to 10000.
|
|
--chunk N log2 of the chunk size. Defaults to 10.
|
|
--actors N log2 of the actor count. Defaults to 2.
|
|
"""
|
|
)
|
|
return false
|
|
end
|
|
end
|
|
|
|
env.out.print(
|
|
"logtable: " + logtable.string() +
|
|
"\niterate: " + iterate.string() +
|
|
"\nlogchunk: " + logchunk.string() +
|
|
"\nlogactors: " + logactors.string()
|
|
)
|
|
true
|
|
|
|
actor Main
|
|
let _env: Env
|
|
let _config: Config = Config
|
|
|
|
var _updates: U64 = 0
|
|
var _confirm: U64 = 0
|
|
let _start: U64
|
|
var _actors: Array[Updater] val
|
|
|
|
new create(env: Env) =>
|
|
_env = env
|
|
|
|
if _config(env) then
|
|
let actor_count = 1 << _config.logactors
|
|
let loglocal = _config.logtable - _config.logactors
|
|
let chunk_size = 1 << _config.logchunk
|
|
let chunk_iterate = chunk_size * _config.iterate
|
|
|
|
_updates = chunk_iterate * actor_count
|
|
_confirm = actor_count
|
|
|
|
var updaters = recover Array[Updater](actor_count) end
|
|
|
|
for i in Range[U64](0, actor_count) do
|
|
updaters.push(Updater(this, actor_count, i, loglocal, chunk_size,
|
|
chunk_iterate * i))
|
|
end
|
|
|
|
_actors = consume updaters
|
|
_start = Time.nanos()
|
|
|
|
for a in _actors.values() do
|
|
a.start(_actors, _config.iterate)
|
|
end
|
|
else
|
|
_start = 0
|
|
_actors = recover Array[Updater] end
|
|
end
|
|
|
|
be done() =>
|
|
if (_confirm = _confirm - 1) == 1 then
|
|
for a in _actors.values() do
|
|
a.done()
|
|
end
|
|
end
|
|
|
|
be confirm() =>
|
|
_confirm = _confirm + 1
|
|
|
|
if _confirm == _actors.size() then
|
|
let elapsed = (Time.nanos() - _start).f64()
|
|
let gups = _updates.f64() / elapsed
|
|
|
|
_env.out.print(
|
|
"Time: " + (elapsed / 1e9).string() +
|
|
"\nGUPS: " + gups.string()
|
|
)
|
|
end
|
|
|
|
actor Updater
|
|
let _main: Main
|
|
let _index: U64
|
|
let _updaters: U64
|
|
let _chunk: U64
|
|
let _mask: U64
|
|
let _loglocal: U64
|
|
|
|
let _output: Array[Array[U64] iso]
|
|
let _reuse: List[Array[U64] iso] = List[Array[U64] iso]
|
|
var _others: (Array[Updater] val | None) = None
|
|
var _table: Array[U64]
|
|
var _rand: U64
|
|
|
|
new create(main:Main, updaters: U64, index: U64, loglocal: U64, chunk: U64,
|
|
seed: U64)
|
|
=>
|
|
_main = main
|
|
_index = index
|
|
_updaters = updaters
|
|
_chunk = chunk
|
|
_mask = updaters - 1
|
|
_loglocal = loglocal
|
|
|
|
_rand = PolyRand.seed(seed)
|
|
_output = _output.create(updaters)
|
|
|
|
let size = 1 << loglocal
|
|
_table = Array[U64].undefined(size)
|
|
|
|
var offset = index * size
|
|
|
|
try
|
|
for i in Range[U64](0, size) do
|
|
_table(i) = i + offset
|
|
end
|
|
end
|
|
|
|
be start(others: Array[Updater] val, iterate: U64) =>
|
|
_others = others
|
|
iteration(iterate)
|
|
|
|
be apply(iterate: U64) =>
|
|
iteration(iterate)
|
|
|
|
fun ref iteration(iterate: U64) =>
|
|
let chk = _chunk
|
|
|
|
for i in Range(0, _updaters) do
|
|
_output.push(
|
|
try
|
|
_reuse.pop()
|
|
else
|
|
recover Array[U64](chk) end
|
|
end
|
|
)
|
|
end
|
|
|
|
for i in Range(0, _chunk) do
|
|
var datum = _rand = PolyRand(_rand)
|
|
var updater = (datum >> _loglocal) and _mask
|
|
|
|
try
|
|
if updater == _index then
|
|
_table(i) = _table(i) xor datum
|
|
else
|
|
_output(updater).push(datum)
|
|
end
|
|
end
|
|
end
|
|
|
|
try
|
|
let to = _others as Array[Updater] val
|
|
|
|
repeat
|
|
let data = _output.pop()
|
|
|
|
if data.size() > 0 then
|
|
to(_output.size()).receive(consume data)
|
|
else
|
|
_reuse.push(consume data)
|
|
end
|
|
until _output.size() == 0 end
|
|
end
|
|
|
|
if iterate > 1 then
|
|
apply(iterate - 1)
|
|
else
|
|
_main.done()
|
|
end
|
|
|
|
be receive(data: Array[U64] iso) =>
|
|
try
|
|
for i in Range(0, data.size()) do
|
|
let datum = data(i)
|
|
var j = (datum >> _loglocal) and _mask
|
|
_table(j) = _table(j) xor datum
|
|
end
|
|
|
|
data.clear()
|
|
_reuse.push(consume data)
|
|
end
|
|
|
|
be done() =>
|
|
_main.confirm()
|
|
|
|
primitive PolyRand
|
|
fun apply(prev: U64): U64 =>
|
|
(prev << 1) xor if prev.i64() < 0 then _poly() else 0 end
|
|
|
|
fun seed(from: U64): U64 =>
|
|
var n = from % _period()
|
|
|
|
if n == 0 then
|
|
return 1
|
|
end
|
|
|
|
var m2 = Array[U64].undefined(64)
|
|
var temp = U64(1)
|
|
|
|
try
|
|
for i in Range(0, 64) do
|
|
m2(i) = temp
|
|
temp = this(temp)
|
|
temp = this(temp)
|
|
end
|
|
end
|
|
|
|
var i: U64 = 64 - n.clz()
|
|
var r = U64(2)
|
|
|
|
try
|
|
while i > 0 do
|
|
temp = 0
|
|
|
|
for j in Range(0, 64) do
|
|
if ((r >> j) and 1) != 0 then
|
|
temp = temp xor m2(j)
|
|
end
|
|
end
|
|
|
|
r = temp
|
|
i = i - 1
|
|
|
|
if ((n >> i) and 1) != 0 then
|
|
r = this(r)
|
|
end
|
|
end
|
|
end
|
|
r
|
|
|
|
fun _poly(): U64 => 7
|
|
|
|
fun _period(): U64 => 1317624576693539401
|