| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- <html>
- <head>
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <style>
- #result { font-size: 48px; }
- #time { font-size: 16px; color: grey; }
- #mybox { padding: 20px; }
- #resultbox { padding: 50px; }
- .bigggg { font-size: 18px; margin-top: 10px; }
- .bigg { font-size: 18px; }
- #url { font-size: 18px; width: 70%; }
- a { text-decoration: none; }
- h1 { padding: 50px; padding-bottom: 0px; font-size: 36px; font-weight: normal; }
- #imagebox { height:224px; width:224px; border: 1px dotted black; }
- #video { height:0px; width:0px; border: 1px dotted black; object-fit: cover;}
- canvas { display: none; }
- * { text-align: center; font-family: monospace; }
- </style>
- <title>tinygrad has WebGPU</title>
- <script src="./net.js"></script>
- <link rel="icon" type="image/x-icon" href="https://raw.githubusercontent.com/tinygrad/tinygrad/master/docs/logo.png">
- </head>
- <body>
- <h1>WebGPU <a href="https://github.com/geohot/tinygrad">tinygrad</a> EfficientNet!</h1>
- <div id="mybox">
- <input type="text" id="url" placeholder="put url here" value="https://upload.wikimedia.org/wikipedia/commons/d/da/Norwegian_hen.jpg">
- <input class="bigg" type="button" onclick="runNetWResource(document.getElementById('url').value)" value="Use URL">
- </div>
- <br/>
- <img id="imagebox"></img>
- <canvas id="canvas" width="200" height="200"> </canvas>
- <div id="resultbox">
- <div id="result">result will go here</div>
- <div id="time"></div>
- </div>
- <script>
- const ctx = document.getElementById("canvas").getContext("2d", { willReadFrequently: true });
- const resultText = document.getElementById('result');
- let labels, net;
- const error = (err) => {
- resultText.innerHTML = `Error: ${err}`;
- throw new Error(err);
- }
- const getDevice = async () => {
- if (!navigator.gpu) error("WebGPU not supported.");
- const adapter = await navigator.gpu.requestAdapter();
- return await adapter.requestDevice();
- };
- const timer = async (func, label = "") => {
- document.getElementById('time').innerHTML = "";
- const start = performance.now();
- const out = await func();
- const delta = (performance.now() - start).toFixed(1)
- console.log(`${delta} ms ${label}`);
- document.getElementById('time').innerHTML = `${delta} ms ${label}`;
- return out;
- }
- const getLabels = async () => (await fetch("https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.json")).json();
- const getSavetensorBuffer = async () => new Uint8Array(await (await fetch("./net.safetensors")).arrayBuffer());
- const reorderChannelsAndRemoveAlpha = (data) => {
- const out = [];
- let i = 0;
- for (let c = 0; c < 3; c++) {
- for (let x = 0; x < 224 * 224; x++) {
- out[i] = data[x * 4 + c];
- i++;
- }
- }
- return out;
- };
- const runNetWResource = async (resource) => {
- resultText.innerHTML = "pending..."
- if (resource == "") error("sir. please type in a URL");
- const response = await fetch(resource)
- if (!response.ok) error("sir. that is not a good URL. try a new one");
- document.getElementById("imagebox").src = resource
-
- const img = new Image();
- img.crossOrigin = "Anonymous";
- img.onload = () => {
- URL.revokeObjectURL(img.src);
- ctx.drawImage(img, 0, 0, 224, 224);
- const data = ctx.getImageData(0, 0, 224, 224).data;
- runNet(data)
- };
- img.src = resource;
- }
- const loadLet = async () => {
- try {
- resultText.innerHTML = "loading..."
- labels = await getLabels();
- const safetensor = await getSavetensorBuffer();
- const device = await getDevice();
- net = await timer(() => setupNet(device, safetensor), "(compilation)");
- resultText.innerHTML = "ready"
- } catch (e) {
- error(e)
- }
- }
- const runNet = async (data) => {
- if (!net) error("Net not loaded yet.");
- const input = reorderChannelsAndRemoveAlpha(Array.from(data).map((pix) => (pix / 255.0) * 0.45 - 0.225));
- const out = await timer(() => net(new Float32Array(input)));
- const arr = Array.from(new Float32Array(out[0]));
- const index = arr.indexOf(Math.max(...arr));
- resultText.textContent = labels[index];
- };
- loadLet();
- </script>
- </body>
- </html>
|