Files

149 lines
6.9 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Merge Selector Lab</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
#trainButton {
width: 100%;
position: relative;
overflow: hidden;
color: white;
background-color: #007bff;
border: none;
}
#trainButton .progress-fill {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: rgba(255, 255, 255, 0.3); /* Transparent overlay */
width: 0;
transition: width 0.1s linear; /* Smooth progress */
}
#downloadButton {
display: none;
margin-top: 1rem;
width: 100%;
}
</style>
</head>
<body>
<div class="container-fluid">
<form id="param-form" class="p-3">
<div class="row">
<div class="form-group col-md-4">
<label for="minPartSize">Min part size:</label>
<input type="text" class="form-control form-control-sm" id="minPartSize" placeholder="Minimum size" value="64KB">
</div>
<div class="form-group col-md-4">
<label for="maxPartSize">Max part size:</label>
<input type="text" class="form-control form-control-sm" id="maxPartSize" placeholder="Maximum size" value="256GB">
</div>
<div class="form-group col-md-4">
<label for="maxWorkers">Max workers:</label>
<input type="text" class="form-control form-control-sm" id="maxWorkers" placeholder="Maximum workers" value="32768">
</div>
</div>
<div class="row">
<div class="form-group col-md-4">
<label for="partsStep">Part size step:</label>
<input type="text" class="form-control form-control-sm" id="partsStep" placeholder="Power of 2 exponent" value="0.25">
</div>
<div class="form-group col-md-4">
<label for="workersStep">Workers step:</label>
<input type="text" class="form-control form-control-sm" id="workersStep" placeholder="Power of 2 exponent" value="0.25">
</div>
</div>
<div class="row mt-3">
<div class="col">
<button type="button" class="btn btn-primary" id="trainButton">
<span id="trainButtonText">Train</span>
<div class="progress-fill"></div>
</button>
<button type="button" class="btn btn-success" id="downloadButton">Download</button>
</div>
</div>
</form>
</div>
<script type="module">
import { MergeTree } from './MergeTree.js';
import { SimulationContainer } from './SimulationContainer.js';
import { sequenceInserter } from './sequenceInserter.js';
import { floatLayerMerges } from './floatLayerMerges.js';
import { subgradientMethod } from './gradientDescent.js';
import { mergeModel } from './mergeModel.js';
import { ModelSolver } from './ModelSolver.js';
import { delayMs, parseHumanReadableSize } from './util.js';
function readSize(name) {
return parseHumanReadableSize(document.getElementById(name).value);
}
function readParams() {
let params = {
minPartSize: readSize('minPartSize'),
maxPartSize: readSize('maxPartSize'),
maxWorkers: readSize('maxWorkers'),
partsStep: readSize('partsStep'),
workersStep: readSize('workersStep'),
};
console.log("PARAMS", params);
return params;
}
document.getElementById('trainButton').addEventListener('click', async () => {
const trainButton = document.getElementById('trainButton');
const progressFill = trainButton.querySelector('.progress-fill');
const trainButtonText = document.getElementById('trainButtonText');
const downloadButton = document.getElementById('downloadButton');
trainButton.disabled = true;
trainButtonText.textContent = 'Training...';
progressFill.style.width = '0%';
downloadButton.style.display = 'none';
const { minPartSize, maxPartSize, maxWorkers, partsStep, workersStep } = readParams();
let solver = new ModelSolver(mergeModel);
await solver.train(minPartSize, maxPartSize, maxWorkers, partsStep, workersStep, subgradientMethod,
async function onProgress({progress, runs_done, runs_total}) {
// Update progress bar (button background)
progressFill.style.width = `${progress}%`;
trainButtonText.textContent = `Training: ${progress}% — ${runs_done}/${runs_total}`;
await delayMs(1);
});
console.log(solver.data);
trainButtonText.textContent = 'Train Again';
trainButton.disabled = false;
// Show the download button
downloadButton.style.display = 'block';
// Set up download functionality
downloadButton.addEventListener('click', () => {
const data = solver.serializeData();
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
let params = [
document.getElementById('minPartSize').value,
document.getElementById('maxPartSize').value,
document.getElementById('maxWorkers').value,
'x' + (1.0 / +document.getElementById('partsStep').value),
'x' + (1.0 / +document.getElementById('workersStep').value),
];
link.download = `solver-${params.join('_')}.json`;
link.click();
URL.revokeObjectURL(url);
}, { once: true });
});
</script>
</body>
</html>