View on GitHub

Accel.js

Accelerating your Node.js program by parallelizing computation with multicores and multinodes.

Index Documentation Archive for 15-418 Competition

Quick Start

Install accel.js:

npm install --save accel

Write a program with computational intensive functions

function cpuIntensive(n) {
    var result=0;
    for (var i=0; i<n; i++) result=Math.random();
    return result;
}

for (var i=10000; i<20000; i++) {
    var result=cpuIntensive(i);
    console.log(result);
}

And accelerate it on your awesome dual core machine!

var accel=require("accel");
var $=accel();

function cpuIntensive(n) {
    var result=0;
    for (var i=0; i<n; i++) result=Math.random();
    return result;
}
$(cpuIntensive);

accel.init();
for (var i=10000; i<20000; i++) {
    $.cpuIntensive(i, (result) => {
        console.log(result);
    });
}

Broadcasting variables? Easy!

var accel=require("accel");
var $=accel();

$.magicNumber1=1103515245;
$.magicNumber2=12345;
$(function generatePseudoRandom(next) {
    next = next * $.magicNumber1 + $.magicNumber2;
    return Math.floor(next/65536) % 32768;
});

accel.init();
$.generatePseudoRandom(50, (res) => {
    console.log(res);
});

Asynchronous function works well, too:

var accel=require("accel");
var $=accel();

$.magicTricks=function(str) {...};
$(function readAndCalculate(callback) {
    fs.readFile('/etc/passwd', 'utf8', (err, data) => {
        callback($.magicTricks(data));
    });
}, "async");

accel.init();
$.readAndCalculate((res) => {
    console.log(res);
});

Initialization

Any application using accel.js should initialize it exactly once, you can specify how many local workers (run on local CPUs) and how many remote workers (run on other machines) are in the workers pool.

You don’t have to wait for the callback before using any functionalities of accel.js. Those who rely on the connections among workers will be deferred automatically.

accel.init(options, [callback])

Broadcast Scope

Broadcast scope is the center of all magic. In your code which is executed remotely, all the local variables are not accessible (of course!) and you can use broadcast scope to make them available.

var $=accel(); will create a new broadcast scope. It is recommended to use separate scope for every .js file to achieve scope isolations. When functions in some scope are executed remotely, the scope will be synchronized automatically and incrementally to broadcast the variables.

The broadcast scope is nothing more than a js-object, just read/write values by $.someKey=someValue or $["someKey"]=someValue.

The scope can also be used as a function, in order to register worker-functions:

Register worker-functions: $(someFunction, [mode])

**Note: **

Invoke worker-functions

For synchronous function, pass all the parameters as normal, plus a trailing function as callback:

function someFunction(arg1, arg2) {}
$(someFunction);
$.someFunction(arg1, arg2, (res) => {
    // now the function has completed
});

For asynchronous function, call the function as it is.

function someAsyncFunc(arg1, arg2, callback) {}
$(someAsyncFunc, "async");
$.someAsyncFunc(arg1, arg2, (params) => {
	// now the function has completed
});

Besides, all the remote functions can be decorated before called:

$.someFunction(arg1, arg2, (res) => { });	// normal invocation
$.someFunction.urgent()(arg1, arg2, (res) => { });	// urgent invocation, the task will be scheduled first
$.someFunction.to(2)(arg1, arg2, (res) => { });	// targeted invocation, the task will be assigned to node 2
$.someFunction.toAll()(arg1, arg2, (res) => { });	// cohert invocation, each node will execute this task exactly once

Homogeneous Dependency

In most cases, it is required to import some packages outside in worker functions. This is achieved by introducing homogeneous dependency:

$.os=accel.require("os");
$.localPackage=accel.require("./localPackage");

$.os.platform();		// you can invoke it locally
$(function() {
    return $.os.platform();	// or invoke it remotely
})((res) => {
    // do something
});

Note: Only use it after assigning to a broadcast scope.

$.os=accel.require("os"); is OK, while var os=accel.require("os"); is not ok.