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

[WIP] Savina Successive Over Relaxation #225

Draft
wants to merge 6 commits into
base: mutation/full
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
67 changes: 67 additions & 0 deletions src/benchmark/sucoverrelax/actor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/* eslint-disable @typescript-eslint/prefer-readonly */
// The SOR (Re)actor
import { InPort, Reactor, State } from "../../core/internal";
import { Message } from "./sorutils";

Check failure on line 4 in src/benchmark/sucoverrelax/actor.ts

View workflow job for this annotation

GitHub Actions / lint

All imports in the declaration are only used as types. Use `import type`

export class SORActor extends Reactor {
constructor(
parent: Reactor,
pos: number,
_value: number,
colour: number,
nx: number,
ny: number,
omega: number,
sorSource: Reactor,
peer: boolean
) {
super(parent, "SORActor");

const x = Math.floor(pos / ny);
const y = pos % ny;

const omegaOverFour = 0.25 * omega;

Check failure on line 23 in src/benchmark/sucoverrelax/actor.ts

View workflow job for this annotation

GitHub Actions / lint

'omegaOverFour' is assigned a value but never used
const oneMinusOmega = 1.0 - omega;

Check failure on line 24 in src/benchmark/sucoverrelax/actor.ts

View workflow job for this annotation

GitHub Actions / lint

'oneMinusOmega' is assigned a value but never used

this.portFromRunner = new InPort<Message>(this);

const neighbours = (() => {

Check failure on line 28 in src/benchmark/sucoverrelax/actor.ts

View workflow job for this annotation

GitHub Actions / lint

'neighbours' is assigned a value but never used
const calPos = (x: number, y: number): number => (x * ny + y);

if (x > 0 && x < nx - 1 && y > 0 && y < ny - 1) {
return [calPos(x, y + 1),
calPos(x + 1, y),
calPos(x, y - 1),
calPos(x - 1, y)];
}
if ((x === 0 || x === (nx - 1)) && (y === 0 || y === (ny - 1))) {
return [
(x === 0) ? calPos(x + 1, y) : calPos(x - 1, y),
(y === 0) ? calPos(x, y + 1) : calPos(x, y - 1)
];
}
if ((x === 0 || x === (nx - 1)) || (y === 0 || y === (ny - 1))) {
if (x === 0 || x === nx - 1) {
return [
(x === 0) ? calPos(x + 1, y) : calPos(x - 1, y),
calPos(x, y + 1),
calPos(x, y - 1)
];
}
return [
(y === 0) ? calPos(x, y + 1) : calPos(x, y - 1),
calPos(x+1, y),
calPos(x-1, y)
];
}
return [];
})();
}

private iter = new State(0);
private maxIter = new State(0);
private msgRcv = new State(0);
private sorActors = new State<Reactor[]>([]);

public portFromRunner: InPort<Message>;
}
71 changes: 71 additions & 0 deletions src/benchmark/sucoverrelax/peer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { InPort, MutationSandbox, OutPort, Reactor, State } from "../../core/internal";
import { SORActor } from "./actor";
import { SORRunner } from "./runner";
import { Message, MessageTypes, SorBorder as SORBorder, SorBorder } from "./sorutils";

export class SORPeer extends Reactor {

s: State<number>;
partStart: State<number>;
matrixPart: State<number[][]>;
border: State<SORBorder>;
sorSource: State<SORRunner>


sorActors: State<Reactor[]>;
public portFromSORRunner: InPort<Message>;

constructor(
parent: Reactor,
s: number,
partStart: number,
matrixPart: number[][],
border: SORBorder,
sorSource: SORRunner
) {
super(parent, "SORPeer");
this.sorActors = new State([]);
this.s = new State(s);
this.partStart = new State(partStart);
this.matrixPart = new State(matrixPart);
this.border = new State(border);
this.sorSource = new State(sorSource);

this.portFromSORRunner = new InPort(this);
}

static boot(this: MutationSandbox, args: BootProcessingArgs) {
const myBorder: SORActor[] = [];
const {_s, border, sorActors, partStart} = args;
const s = _s.get();
const partStartVal = partStart.get();

const sorActorsValue = sorActors.get();
const borderValue = border.get();
for (let i = 0; i < s; ++i) {
sorActorsValue[i * (s - partStartVal + 1)] = borderValue.borderActors[i];
}
sorActors.set(sorActorsValue);

for ()

Check failure on line 50 in src/benchmark/sucoverrelax/peer.ts

View workflow job for this annotation

GitHub Actions / jest

Expression expected.
}

Check failure on line 51 in src/benchmark/sucoverrelax/peer.ts

View workflow job for this annotation

GitHub Actions / jest

Expression expected.
}

interface BootProcessingArgs {
type: MessageTypes.sorBootMessage,
_s: State<number>,
border: State<SORBorder>,
sorActors: State<SORActor[]>,
partStart: State<number>,
}
interface ResultProcessingArgs {
type: MessageTypes.sorResultMessage,
expectingBoot: State<boolean>,
totalMsgRcv: State<number>,
returned: State<number>,
gTotal: State<number>,
s: State<number>,
part: State<number>
}

type ProcessingArgs = BootProcessingArgs | ResultProcessingArgs;
126 changes: 126 additions & 0 deletions src/benchmark/sucoverrelax/runner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { InMultiPort, InPort, MutationSandbox, OutMultiPort, OutPort, Parameter, Reactor, State, Variable, } from "../../core/internal";
import { SORActor } from "./actor";
import { SORPeer, SORPeer } from "./peer";
import { Message, MessageTypes, SORBootMessage, SORBorderMessage, SORResultMessage, SORStartMessage, SorBorder, arrayOfDim, jacobi, omega, randomMatrix } from "./sorutils";

export class SORRunner extends Reactor {
protected s: State<number>;
protected part: State<number>;

protected sorActors: State<SORActor[]>;
protected sorPeer: State<SORPeer | undefined>;

// Definition of Ports. Initialisation will take place in the constructor, because some of them needs to access
// some parametres.
/// Runner will interact with App. It will receive BootMsg, and send ResultMsg.
/// In the original Savina benchmark suite there is no ResultMsg.
/// Instead, Runner handles validation and simply quits the programme.
/// We are taking a more based approach but there is no difference.
/// See https://github.com/shamsimam/savina/blob/52e546959a57670cdba7a88f0a030b53cfdb16d6/src/main/scala/edu/rice/habanero/benchmarks/sor/SucOverRelaxAkkaActorBenchmark.scala#L112-L115
protected portFromApp: InPort<SORBootMessage>;
protected portToApp: OutPort<unknown[]>;

/// Runner will send StartMsg to all actors, and receive ResultMsg from all actors.
/// Runner will also supply them with a the list of actors. We will do the same, connection will be handled by individual Actors.
protected portsFromActors: InMultiPort<SORResultMessage>;
protected portsToActors: OutMultiPort<SORStartMessage>;

/// Runner will send BootMsg to Peer, and receive BorderMsg OR ResultMsg from Peer.
/// I am using a 3-port approach here, this way I can handle SORResultMessage in a single mutation.
protected portFromPeerBorder: InPort<SORBorderMessage>;
protected portFromPeerResult: InPort<SORResultMessage>;
protected portToPeer: OutPort<SORBootMessage>;

protected gTotal = new State(0.0);
protected returned = new State(0);
protected totalMsgRcv = new State(0);
protected expectingBoot = new State(true);

// In Savina, randoms is accessed directly from SucOverRelaxConfig.
// Here we pass it in to the closure.
constructor(parent: Reactor, s: number, _randoms: number[][]) {
super(parent);
this.s = new State(s);
// In the scala implementation a simple /2 was used.
// In JS we might need to enforce some sort of guarantee as it was used to calculate position
const part = Math.floor(s / 2);
this.part = new State(part);

// The following lines are from Savina. They should be rather irrelevant, actually, because message passing are handled by ports
this.sorActors = new State([]);
this.sorPeer = new State(undefined);

// Initialisation of ports
this.portFromApp = new InPort(this);
this.portToApp = new OutPort(this);
// size * (part + 1) is the size of sorActors in the Savina benchmark
this.portsFromActors = new InMultiPort(this, s * (part + 1));
this.portsToActors = new OutMultiPort(this, s * (part + 1));

this.portFromPeerBorder = new InPort(this);
this.portFromPeerResult = new InPort(this);
this.portToPeer = new OutPort(this);

this.addMutation(
[this.startup],
[],
function (this) {
console.log("I am SORRunner [M1]. I am trolling.")
}
);

// SORRunner::process(msg: SorBootMessage) and SORRunner::boot
this.addMutation(
[this.portFromApp],
[this.portFromApp, this.expectingBoot, this.sorActors, this.sorPeer, this.writable (this.portToPeer)],
function(this, portFromApp, expectingBoot, sorActorsState, sorPeerState, portToPeer) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const randoms = portFromApp.get()!.A!;

const sorActors = sorActorsState.get();
expectingBoot.set(false);
// SORRunner::boot
const myBorder: SORActor[] = [];
// In Scala/Akka, 0 until s is [0, s)
for (let i = 0; i < s; ++i) {
let c = i % 2;
for (let j = 0; j < part; ++j) {
const pos = i * (part + i) + j;
c = 1 - c;
sorActors[pos] = this.addSibling(SORActor, pos, randoms[i][j], c, s, part + 1, omega, this.getReactor(), false);
if (j === (part - 1)) {
myBorder[i] = sorActors[pos];
}
}
}
const partialMatrix = arrayOfDim([s, s - part], 0 as number);
for (let i = 0; i < s; ++i) {
for (let j = 0; j < s - part; ++j) {
partialMatrix[i][j] = randoms[i][j + part];
}
}
const sorPeer = this.addSibling(SORPeer, s, part, partialMatrix, new SorBorder(myBorder), this.getReactor() as SORRunner);
this.connect(portToPeer.getPort(), sorPeer.portFromSORRunner);
sorPeerState.set(sorPeer);
portToPeer.set({
messageType: MessageTypes.sorBootMessage,
A: undefined
});
}
);

this.addMutation(
[this.portsFromActors, this.portFromPeerResult],
[this.portsFromActors, this.portFromPeerResult, this.totalMsgRcv],
function (this, portsFromActors, portFromPeerResult, totalMsgRcvState) {
const message =

const totalMsgRcv = totalMsgRcvState.get();

Check failure on line 118 in src/benchmark/sucoverrelax/runner.ts

View workflow job for this annotation

GitHub Actions / jest

Expression expected.

}
);

}


}
Loading
Loading