Skip to content

Commit bce6352

Browse files
committed
[need squash] wip
1 parent 7413e83 commit bce6352

File tree

6 files changed

+352
-0
lines changed

6 files changed

+352
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* eslint-disable @typescript-eslint/prefer-readonly */
2+
// The SOR (Re)actor
3+
import { Reactor, State } from "../../core/internal";
4+
5+
export class SORActor extends Reactor {
6+
constructor(
7+
parent: Reactor,
8+
pos: number,
9+
_value: number,
10+
colour: number,
11+
nx: number,
12+
ny: number,
13+
omega: number,
14+
sorSource: Reactor,
15+
peer: boolean
16+
) {
17+
super(parent, "SORActor");
18+
19+
const x = Math.floor(pos / ny);
20+
const y = pos % ny;
21+
22+
const omegaOverFour = 0.25 * omega;
23+
const oneMinusOmega = 1.0 - omega;
24+
25+
const neighbours = (() => {
26+
const calPos = (x: number, y: number): number => (x * ny + y);
27+
28+
if (x > 0 && x < nx - 1 && y > 0 && y < ny - 1) {
29+
return [calPos(x, y + 1),
30+
calPos(x + 1, y),
31+
calPos(x, y - 1),
32+
calPos(x - 1, y)];
33+
}
34+
if ((x === 0 || x === (nx - 1)) && (y === 0 || y === (ny - 1))) {
35+
return [
36+
(x === 0) ? calPos(x + 1, y) : calPos(x - 1, y),
37+
(y === 0) ? calPos(x, y + 1) : calPos(x, y - 1)
38+
];
39+
}
40+
if ((x === 0 || x === (nx - 1)) || (y === 0 || y === (ny - 1))) {
41+
if (x === 0 || x === nx - 1) {
42+
return [
43+
(x === 0) ? calPos(x + 1, y) : calPos(x - 1, y),
44+
calPos(x, y + 1),
45+
calPos(x, y - 1)
46+
];
47+
}
48+
return [
49+
(y === 0) ? calPos(x, y + 1) : calPos(x, y - 1),
50+
calPos(x+1, y),
51+
calPos(x-1, y)
52+
];
53+
}
54+
return [];
55+
})();
56+
}
57+
58+
private iter = new State(0);
59+
private maxIter = new State(0);
60+
private msgRcv = new State(0);
61+
private sorActors = new State<Reactor[]>([]);
62+
63+
protected
64+
}

src/benchmark/sucoverrelax/peer.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { Reactor, State } from "../../core/internal";
2+
import { SORRunner } from "./runner";
3+
import { SorBorder } from "./sorutils";
4+
5+
export class SORPeer extends Reactor {
6+
sorActors: State<Reactor[]>;
7+
constructor(
8+
parent: Reactor,
9+
s: number,
10+
partStart: number,
11+
matrixPart: number[][],
12+
border: SorBorder,
13+
sorSource: SORRunner
14+
) {
15+
super(parent, "SORPeer");
16+
this.sorActors = new State([]);
17+
}
18+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { InMultiPort, InPort, OutMultiPort, OutPort, Parameter, Reactor, State, } from "../../core/internal";
2+
import { SORActor } from "./actor";
3+
import { SORPeer } from "./peer";
4+
import { Message, SorBorder, omega } from "./sorutils";
5+
6+
export class SORRunner extends Reactor {
7+
protected sorActors: State<Reactor[]>;
8+
protected sorPeer: State<Reactor | undefined>;
9+
10+
protected portToSORActors: OutPort<Message>;
11+
protected portToSORPeer: OutPort<Message>;
12+
// Unsure if this would work, let's just try......
13+
protected portFromSORActor: InPort<Message>;
14+
protected portFromSORPeer: InPort<Message>;
15+
16+
constructor(parent: Reactor, size: number, _randoms: number[][]) {
17+
super(parent, "SORRunner");
18+
// These are in SorRunner;
19+
const s = size;
20+
// In the scala implementation a simple /2 was used.
21+
// In JS we might need to enforce some sort of guarantee as it was used to calculate position
22+
const part = Math.floor(s / 2);
23+
/** These are from Savina. They should be rather irrelevant, actually. */
24+
this.sorActors = new State([]);
25+
this.sorPeer = new State(undefined);
26+
27+
/** These are the actual messaging passing mechanism that are synonomous to that of Savina. */
28+
// This creates a bunch of ports.
29+
this.portToSORActors = new OutPort(this);
30+
this.portToSORPeer = new OutPort(this);
31+
32+
// SorRunner::boot()
33+
this.addMutation(
34+
[this.startup],
35+
[this.sorActors, this.sorPeer],
36+
function (this, sorActors, sorPeer) {
37+
const myBorder: Reactor[] = [];
38+
const randoms = _randoms;
39+
40+
// In scala, (i <- 0 until s) is loop excluding s.
41+
const sorActorsValue = sorActors.get();
42+
for (let i = 0; i < s; ++i) {
43+
let c = i % 2;
44+
for (let j = 0; j < part; ++j) {
45+
const pos = i * (part + 1) + j;
46+
c = 1 - c;
47+
// We modify them in bulk, then update the state.
48+
// Unlike in Scala we do not need to initialise the array here, JS supports sparse array.
49+
// I have absolutely no idea why these parametres are called as such......
50+
sorActorsValue[pos] = this.getReactor()._uncheckedAddSibling(
51+
SORActor,
52+
pos, randoms[i][j], c, s, part + 1, omega, this.getReactor(), false
53+
);
54+
// TODO: Make connections
55+
if (j === (part - 1)) {
56+
myBorder[i] = sorActorsValue[pos];
57+
}
58+
59+
}
60+
}
61+
sorActors.set(sorActorsValue);
62+
63+
const partialMatrix: number[][] = [];
64+
for (let i = 0; i < s; ++i) {
65+
for (let j = 0; j < s - part; ++j) {
66+
partialMatrix[i][j] = randoms[i][j + part];
67+
}
68+
}
69+
70+
const sorPeerValue = this.getReactor()._uncheckedAddSibling(
71+
SORPeer,
72+
s, part, partialMatrix, new SorBorder(myBorder),
73+
// A dirty hack. Maybe this will be removed as ports get added.
74+
this.getReactor() as SORRunner
75+
);
76+
sorPeer.set(sorPeerValue);
77+
// TODO: Add connections.
78+
79+
}
80+
);
81+
}
82+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { Reactor } from "../../core/reactor";
2+
3+
// Savina implementation of PRNG
4+
export class SavinaPRNG {
5+
private value: number;
6+
7+
constructor(value?: number) {
8+
this.value = value ?? 1145141919;
9+
}
10+
11+
public nextNumber(): number {
12+
this.value = ((this.value * 1309) + 13849) & 65535;
13+
return this.value;
14+
}
15+
16+
public nextFloat(): number {
17+
return 1.0 / (this.nextNumber() + 1);
18+
}
19+
}
20+
21+
// This is not a recommended way to use JS, but whatever......
22+
23+
export const refVal = [
24+
0.000003189420084871275,
25+
0.001846644602759566,
26+
0.0032099996270638005,
27+
0.0050869220175413146,
28+
0.008496328291240363,
29+
0.016479973604143234,
30+
0.026575660248076397,
31+
// This is different from the Savina one because JS doesn't have high precision
32+
1.026575660248076,
33+
2.026575660248076,
34+
3.026575660248076
35+
];
36+
37+
export const jacobi = 100;
38+
39+
export const omega = 1.25;
40+
41+
export function randomMatrix(m: number, n: number): number[][] {
42+
const mat = [];
43+
const prng = new SavinaPRNG(114514);
44+
for (let i = 0; i < m; ++i) {
45+
const row = [];
46+
for (let j = 0; j < n; ++j) {
47+
row.push(prng.nextFloat() * 1e-6);
48+
}
49+
mat.push(row);
50+
}
51+
return mat;
52+
}
53+
54+
export function jgfValidate(gTotal: number, size: number): void {
55+
const dev = Math.abs(gTotal - refVal[size]);
56+
if (dev > 1.0e-12) {
57+
console.log("Validation failed");
58+
console.log(`GTotal=${gTotal}; ${refVal[size]}; ${dev}; ${size}`);
59+
} else {
60+
console.log("Validation OK!");
61+
}
62+
}
63+
64+
export enum MessageTypes {
65+
sorBorderMessage,
66+
sorStartMessage,
67+
sorValueMessage,
68+
sorBootMessage,
69+
sorResuleMessage
70+
}
71+
72+
export class SorBorder {
73+
borderActors: Reactor[];
74+
constructor(borderActors: Reactor[]) {
75+
this.borderActors = borderActors;
76+
}
77+
}
78+
79+
export interface Message {
80+
messageType: MessageTypes;
81+
}
82+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import {
2+
type WritablePort,
3+
Parameter,
4+
InPort,
5+
OutPort,
6+
State,
7+
Action,
8+
Reactor,
9+
App,
10+
TimeValue,
11+
Origin,
12+
Log
13+
} from "../../core/internal";
14+
15+
16+
17+
18+
19+
20+

src/benchmark/sucoverrelax/test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { App, InPort, OutPort, Reactor } from "../../core/internal";
2+
3+
class Master extends Reactor {
4+
outp: OutPort<number>;
5+
6+
constructor(parent: Reactor, receivers: Receiver[]) {
7+
super(parent, "");
8+
this.outp = new OutPort(this);
9+
10+
this.addMutation(
11+
[this.startup],
12+
[this.outp],
13+
function(this, outp) {
14+
let i = 0;
15+
for (const r of receivers) {
16+
console.log(`Master: triggering ${i}`)
17+
this.connect(outp, r.inp);
18+
this.getReactor().writable(outp).set(i++);
19+
this.disconnect(outp, r.inp);
20+
}
21+
}
22+
);
23+
}
24+
}
25+
26+
class Receiver extends Reactor {
27+
inp: InPort<number>;
28+
outp: OutPort<number>;
29+
30+
constructor(parent: Reactor, receiver2: Receiver2) {
31+
super(parent, "");
32+
this.inp = new InPort(this);
33+
this.outp = new OutPort(this);
34+
35+
this.addMutation(
36+
[this.inp],
37+
[this.inp, this.outp],
38+
function(this, inp, outp) {
39+
const message = inp.get();
40+
if (message == null) {
41+
throw Error("Receiver: Message is null.");
42+
}
43+
console.log(`Receiver: message ${message}. Sending.`);
44+
this.connect(outp, receiver2.inp);
45+
this.getReactor().writable(outp).set(message);
46+
this.disconnect(outp, receiver2.inp);
47+
}
48+
);
49+
}
50+
}
51+
52+
class Receiver2 extends Reactor {
53+
inp: InPort<number>;
54+
55+
constructor(parent: Reactor) {
56+
super(parent, "");
57+
this.inp = new InPort(this);
58+
59+
this.addReaction(
60+
[this.inp],
61+
[this.inp],
62+
function (this, inp) {
63+
console.log(`Receiver2: received ${inp.get()}`)
64+
}
65+
);
66+
}
67+
}
68+
69+
class Apppp extends App {
70+
master: Master;
71+
recvs: Receiver[];
72+
recv2: Receiver2;
73+
74+
constructor() {
75+
super(undefined, undefined, false, ()=>(undefined), ()=>(undefined), "");
76+
this.recv2 = new Receiver2(this);
77+
this.recvs = [];
78+
for (let i = 0; i < 10; ++i) {
79+
this.recvs.push(new Receiver(this, this.recv2));
80+
}
81+
this.master = new Master(this, this.recvs);
82+
}
83+
}
84+
85+
const app = new Apppp();
86+
app._start();

0 commit comments

Comments
 (0)