JavaScript is dynamically typed
var a = 10;
typeof(a); /* -> number */
a += "text"
typeof(a); /* -> string */
JavaScript has no integer type
var a = 10;
typeof(a); /* -> number */
var b = 10.0;
typeof(b); /* -> number */
All arrays are hash tables
var a = Array(2);
a[0] = 1; /* OK */
a[1] = 2; /* OK */
a["hello"] = "world"; /* OK! */
var b = a[10]; /* OK!! */
b; /* -> undefined!!! */
Elements are dynamically typed
var a = Array();
a[0] = 42;
a[0] = "GATech"; /* OK */
No blocking operations supported
callLongRunningOperation(normalArgs, function () {
/* Callback code */
});
Event handlers must finish fast
function DGEMM(a, b, c, size) {
for (var i = 0; i < size; ++i) {
for (var j = 0; j < size; ++j) {
var sum = c[i*size+j];
for (var k = 0; k < size; ++k) {
sum += a[i*size+k] * b[k*size+j];
}
c[i*size+j] = sum;
}
}
};
function ZGEMM(a, b, c, size) {
for (var i = 0; i < size; ++i) {
for (var j = 0; j < size; ++j) {
var sumReal = c[2*(i*size+j)];
var sumImag = c[2*(i*size+j)+1];
for (var k = 0; k < size; ++k) {
var aReal = a[2*(i*size+k)];
var aImag = a[2*(i*size+k)+1];
var bReal = b[2*(k*size+j)];
var bImag = b[2*(k*size+j)+1]
sumReal += aReal * bReal - aImag * bImag;
sumImag += aReal * bImag + aImag * bReal;
}
c[2*(i*size+j)] = sumReal;
c[2*(i*size+j)+1] = sumImag;
}
}
};
Typed arrays provide a way of compact storage for numeric types
/* 1KB memory chunk */
var ab = ArrayBuffer(1024);
/* View of the memory chunk as 256 32-bit integers */
var i32Array = Int32Array(ab);
i32Array[7] = 10;
/* View of the memory chunk as 256 single-precision floats */
var f32Array = Float32Array(ab);
f32Array[8] = 3.14159265359;
/* View of the memory chunk as 128 double-precision floats */
var f64Array = Float64Array(ab);
f64Array[0] = 2.7182818284590452353;
Emscripten compiles to Asm.js
double dotProduct(double* x, int len) {
double s = 0.0;
for (int i = 0; i < len; ++i) {
s += *x++;
}
return s;
}
Asm.js is, in fact, statically typed
function dotProduct(x, len) {
x = x|0;
len = len|0;
var i = 0, s = 0.0;
for (i = 0; (i|0) < (len|0); i = (i + 1)|0) {
s = s + (+HEAP64F[x>>3]);
x = (x + 8)|0
}
return +s;
}
Portable Native Client enables Web browser to run web apps pre-compiled to LLVM-based bitcode.
PNaCl is independent of JavaScript, and is free of its limitations.
Portable Native Client (PNaCl) | Emscripten/Asm.js | |
---|---|---|
SIMD | Yes (SP only) | Experimental |
Shared memory parallelism | Yes (pthreads) | In discussion |
64-bit integers | Supported natively | Emulated with 32-bit ops |
Can run in | Chromium | All browsers (fast in Firefox) |
Web Workers enable multi-core execution in JavaScript
Web Workers can do long-running computations, but can not access or modify the content of the Web page
Web Workers are not threads, they are processes: message passing is the only way of communication
Objects can be copied or transfered to a Web Worker, but not shared
This material is based upon work supported by the U.S. Department of Energy (DOE), Office of Science, Office of Advanced Scientific Computing Research, X-Stack program under Award Number DE-FC02-10ER26006/DE-SC0004915; as well as grants from the U.S. National Science Foundation (NSF) Award Number 1339745 and CAREER Award Number 0953100.
Special thank you to AMD, who hired me for a summer internship to start the Furious.js project and made it open-source.
BLIS ports for Portable Native Client and Emscripten are available from BLIS repo as pnacl and emscripten configurations
BLIS for Portable Native Client is also available from NaClPorts as blis package
GEMM benchmarks used in this presentation are released on GitHub.com/Maratyszcza/blis-bench
Furious.js is currently developed on GitHub.com/HPCGarage/Furious.js