Published
Edited
May 11, 2022
Insert cell
Insert cell
Insert cell
arr = {
let a = new Float64Array(1024 * 1024 * 64);
return a
}
Insert cell
{for (let i = 0; i<arr.length; i++)arr[i] = 1;}
Insert cell
Insert cell
every_element = {
function every_element(arr){
for (let i = 0; i<arr.length; i++) arr[i] +=1;
}
return time_me(every_element);
}
Insert cell
every_8_elements = {
function every_8_elements(arr){
for (let i=0; i<arr.length; i+=8) arr[i] +=1;
}
return time_me(every_8_elements);
}
Insert cell
Insert cell
every_element(arr)
Insert cell
every_8_elements(arr)
Insert cell
Insert cell
md`
* timing widget for getting statistically accurate samples of times for individual functions
* showing a nice plot of the samples and convergence (distribution)
* have a play button there to allow users to start the computation
* run it on a background thread?
`
Insert cell
md`Another example of this is Instruction Level Parallelism...`
Insert cell
b = new Float64Array(2);
Insert cell
parallel = time_me(()=>{for (let i = 0; i<arr.length; i++) { b[0]++; b[1]++}})
Insert cell
bound = time_me(()=> {for (let i = 0; i<arr.length; i++) { b[0]++; b[0]++}})
Insert cell
parallel()
Insert cell
bound()
Insert cell
md`
## Cache Size
| level | size |
|-------|------|
| L1 | 32K |
| L2 | 256K |
| L3 | 16MB |
`
Insert cell
scatterplot.svg.node()
Insert cell
md`LogY: ${viewof log}`
Insert cell
scatterplot.y(val)
Insert cell
val
Insert cell
viewof val = html`<input type=range min=0 max=1 step=any>`;
Insert cell
{
scatterplot.update(median_data)
}
Insert cell
viewof log = html`<input type=checkbox />`;
Insert cell
scatterplot.init()
Insert cell
scatterplot = {
return {
init: function init(){
this.svg = d3.create("svg")
.attr("viewBox", [0,0,width,height]);

if (!(log)){
this.y = d3.scaleLinear()
.domain([0,10]).nice()
.range([height - margin.bottom, margin.top])
}

if (log){
this.y = d3.scaleLog()
.base(10)
.domain([0.1, 200])//.nice()
// .domain(d3.extent(data, d=>d.time)).nice()
.range([height - margin.bottom, margin.top])
.clamp(true);
}

this.x = d3.scaleLinear()
.domain([0,10]).nice()
.range([margin.left, width - margin.right])

this.xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(this.x).ticks(width / 80))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", width)
.attr("y", margin.bottom - 4)
.attr("fill", "currentColor")
.attr("text-anchor", "end")
.text("Size (MB)"))

this.yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(this.y))
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", -margin.left)
.attr("y", 10)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.text("time (ms)"))


this.svg.append("g")
.attr("class", "y axis")
.call(this.yAxis);

this.svg.append("g")
.attr("class", "x axis")
.call(this.xAxis);
},


update: function (new_data){

this.x.domain(d3.extent(new_data, d=>d.size));

if (!(log)) this.y.domain(d3.extent(new_data, d=>d.time));
if (log) this.y.domain([0.0001, d3.max(new_data, d=>d.time)]);



this.svg.select(".x.axis")
// .transition()
.call(this.xAxis);

this.svg.select(".y.axis")
// .transition()
.call(this.yAxis);

let plot = this;
function onMouseOver(d,i,c){
console.log(d,i,c);
// Specify where to put label of text
debugger;
plot.svg.append('text')
.attr('id', "t" + i.size + "-" + i.type)
.attr('x', plot.x(i.size) + 3)
.attr('y', plot.y(i.time) - 5)
.text(i.dim + ' - ' + i.samples);
}

function onMouseOut(d,i){
// Select text by id and then remove
d3.select("#"+CSS.escape("t" + i.size + "-" + i.type)).remove(); // Remove text location
}

let circle = this.svg//.append("g")
.selectAll("circle")
.data(new_data, d=>{
let key = d.type+d.size
return d? key:this.id;
});
// circle.exit().remove();
// debugger;
circle.join(
enter => enter.append('circle')
.attr("stroke-width", 0.5)
// .attr("fill", "none")
.attr("r", 0)
.attr("cx", d => {
return this.x(d.size)
})
.attr("cy", d => {
return this.y(d.time);
})
.attr("stroke", d => {
if(d.type == "row_major") return "red";
if(d.type == "col_major") return "blue";
})
.attr("fill", d => {
if(d.type == "row_major") return "red";
if(d.type == "col_major") return "blue";
})
.on("mouseover", onMouseOver)
.on("mouseout", onMouseOut)
.transition()
.attr("r", 1)
,

update => update.transition()
.attr("cy", d => this.y(d.time))
.attr("cx", d=>this.x(d.size))
,
exit => exit.remove()
)


}

}
}

Insert cell
Insert cell
function make_data(){

function make_matrix(dim){
let mat = new Uint32Array(dim*dim);
for(let i=0; i<dim*dim; i++){
mat[i] = 1;
}
mat.get = function(x,y,dim){
return this[x*dim + y];
}
return mat;
}

function row_major(mat, dim){
let tot = 0;
for (let y=0; y<dim; y++){
for (let x=0; x<dim; x++){
tot += mat.get(x,y, dim);
}
}
return tot;
}

function col_major(mat, dim){
let tot = 0;
for (let x=0; x<dim; x++){
for (let y=0; y<dim; y++){
tot += mat.get(x,y, dim);
}
}
return tot;
}

function time_me(wrapped){
return function(){
const start = performance.now();
wrapped.apply(this, arguments);
const end = performance.now();
return end - start;
}
}

let cm_time = time_me(col_major);
let rm_time = time_me(row_major);
let times = [];
let max = 4200;
//give the jit a chance to work
let mat = make_matrix(max);
rm_time(mat, max);
cm_time(mat, max);

let step = 1;
let sizes = [];
for (let i=0; i<50; i++){
let num = Math.ceil(Math.random() * max);
num = num + (step - num%step)
sizes.push(num);
}
// debugger;
for (let d of sizes){
let size = (d * d * 4) / Math.pow(10,6);
// let mat = make_matrix(d);
// debugger;
let row_time = rm_time(mat, d);
let col_time = cm_time(mat, d);
times.push({
type: 'col_major',
time: col_time,
size: size,
dim: d
});
times.push({
type: 'row_major',
time: row_time,
size: size,
dim: d
});
}
return times;
}
Insert cell
w = {
function W(func) {
function job(func) {}

function workerMessageHandler(e, handler) {
console.log(`Worker: ${e}`);
postMessage(handler());
}

job.prototype.blob = function() {
const code = `
${func.toString()}
const handler = ${func.name}
${workerMessageHandler.toString()}
this.onmessage = (e) => {
workerMessageHandler(e.data, handler)
}
`;

return code;
};

job.prototype.worker = function() {
const blob = new Blob([this.blob()], { type: 'text/javascript' });
const url = URL.createObjectURL(blob);

this.w = new Worker(url);
return this.w;
};

return new job(func);
}

const job = W(make_data);
const w = job.worker();

function calc(){
if (w.run) w.postMessage(null);
}

w.onmessage = m => {
console.log(m);
// m.data.forEach(x=>_data.push(x));
// mutable data.push(...m.data);
mutable data = data.concat(m.data);
requestAnimationFrame(calc);
};
return w;
}
Insert cell
w.postMessage(null)
Insert cell
w.run = run;
Insert cell
w.run
Insert cell
run
Insert cell
Insert cell
test_array = [1,2,3,4,5]
Insert cell
test_array.slice(1,4)
Insert cell
test_array.slice(Math.round(test_array.length * 0.2), Math.round(test_array.length * 0.8))
Insert cell
median_data = Array.from(
d3.rollup(data,
x=>{
let times = x.map(x=>x.time).sort();
if (times.length > 5){
times = times.slice(Math.round(times.length * 0.2), Math.round(times.length * 0.8))
}
let time = d3.mean(times);
if (time === undefined){
debugger;
console.log("undefined time value");
}
return {
size: x[0].size,
type: x[0].type,
time: time,
dim: x[0].dim,
samples: x.length
};
},
x=>x.type,
x=>x.size)
.values())
.map(x=> Array.from(x.values()))
.flat();
Insert cell
d3.quantile(d3.range(10), 1)
Insert cell
a = [3,6,4,5]
Insert cell
a.sort()
Insert cell
Insert cell
height = 500;
Insert cell
d3 = require("d3")
Insert cell
d3.version
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more