Usando GPU para melhorar o desempenho do JavaScript

 

Usando GPU para melhorar o desempenho do JavaScript

Torne suas aplicações 10 vezes mais rápidas com GPU.js

Chameera Dulanga
30 de Março · 8 min de leitura

Mas você já pensou em combinar o poder da GPU em seus aplicativos web para aumentar o desempenho?

O que é GPU.js e por que devemos usá-la?

Fonte: https://gpu.rocks/#/

Em suma, GPU.js é uma biblioteca de aceleração JavaScript que pode ser usada para cálculos de uso geral em GPUs usando JavaScript. Ele suporta navegadores, Node.js e TypeScript.

Como configurar GPU.js?

Para projetos de Nó

npm install gpu.js --save
or
yarn add gpu.js
import { GPU } from ('gpu.js')
--- or ---
const { GPU } = require('gpu.js')
--- or ---
import { GPU } from 'gpu.js'; // Use this for TypeScript
const gpu = new GPU();

Para Bowsers

<script src="dist/gpu-browser.min.js"></script>--- or ---<script 
src="https://unpkg.com/gpu.js@latest/dist/gpu- browser.min.js">
</script>
<script
rc="https://cdn.jsdelivr.net/npm/gpu.js@latest/dist/gpu-browser.min.js">
</script>
<script>
const gpu = new GPU();
...
</script>

Dica: Construir e compartilhar componentes independentes com bit

Componentes de interface do usuário de material compartilhados individualmente em Bit.dev

Criando funções

const exampleKernel = gpu.createKernel(function() {
...
}, settings);
const settings = {
output: [100]
};

Variáveis suportadas para kernels

número

const exampleKernel = gpu.createKernel(function() {
const number1 = 10;
const number2 = 0.10;
return number1 + number2;
}, settings);

booleano

const kernel = gpu.createKernel(function() {
const bool = true;
if (bool) {
return 1;
}else{
return 0;
}
},settings);

Matrizes

const exampleKernel = gpu.createKernel(function() {
const array1 = [0.01, 1, 0.1, 10];
return array1;
}, settings);

Funções

const exampleKernel = gpu.createKernel(function() {
function privateFunction() {
return [0.01, 1, 0.1, 10];
}
return privateFunction();
}, settings);

Tipos de entrada suportados

Números

const exampleKernel = gpu.createKernel(function(x) {
return x;
}, settings);
exampleKernel(25);

Matriz 1D,2D ou 3D de Números

const exampleKernel = gpu.createKernel(function(x) {
return x;
}, settings);
exampleKernel([1, 2, 3]);
const { input } = require('gpu.js');
const value = input(flattenedArray, [width, height, depth]);

Imagens HTML

//Single Imageconst kernel = gpu.createKernel(function(image) {
...
})
.setGraphical(true)
.setOutput([100, 100]);

const image = document.createElement('img');
image.src = 'image1.png';
image.onload = () => {
kernel(image);
document.getElementsByTagName('body')[0].appendChild(kernel.canvas);
};
//Multiple Imagesconst kernel = gpu.createKernel(function(image) {
const pixel = image[this.thread.z][this.thread.y][this.thread.x];
this.color(pixel[0], pixel[1], pixel[2], pixel[3]);
})
.setGraphical(true)
.setOutput([100, 100]);

const image1 = document.createElement('img');
image1.src = 'image1.png';
image1.onload = onload;
....
//add another 2 images
....
const totalImages = 3;
let loadedImages = 0;
function onload() {
loadedImages++;
if (loadedImages === totalImages) {
kernel([image1, image2, image3]);
document.getElementsByTagName('body')[0].appendChild(kernel.canvas);
}
};

Primeira função usando GPU.js

Passo 1 — Função para gerar matrizes numésias com 1000 elementos

generateMatrices() {
this.matrices = [[], []];
for (let y = 0; y < this.matrixSize; y++) {
this.matrices[0].push([])
this.matrices[1].push([])
for (let x = 0; x < this.matrixSize; x++) {
const value1 = parseInt((Math.random() * 10).toString())
const value2 = parseInt((Math.random() * 10).toString())
this.matrices[0][y].push(value1)
this.matrices[1][y].push(value2)
}
}
}

Passo 2 — Função do kernel

gpuMultiplyMatrix() {
const gpu = new GPU();
const multiplyMatrix = gpu.createKernel(function (a: number[][], b: number[][], matrixSize: number) {
let sum = 0;

for (let i = 0; i < matrixSize; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([this.matrixSize, this.matrixSize])
const startTime = performance.now();
const resultMatrix = multiplyMatrix(this.matrices[0], this.matrices[1], this.matrixSize);

const endTime = performance.now();
this.gpuTime = (endTime - startTime) + " ms";

console.log("GPU TIME : "+ this.gpuTime);
this.gpuProduct = resultMatrix as number[][];
}

Passo 3: função de multiplicação da CPU.

cpuMutiplyMatrix() {
const startTime = performance.now();
const a = this.matrices[0];
const b = this.matrices[1];
let productRow = Array.apply(null, new Array(this.matrixSize)).map(Number.prototype.valueOf, 0);
let product = new Array(this.matrixSize);

for (let p = 0; p < this.matrixSize; p++) {
product[p] = productRow.slice();
}

for (let i = 0; i < this.matrixSize; i++) {
for (let j = 0; j < this.matrixSize; j++) {
for (let k = 0; k < this.matrixSize; k++) {
product[i][j] += a[i][k] * b[k][j];
}
}
}
const endTime = performance.now();
this.cpuTime = (endTime — startTime) + “ ms”;
console.log(“CPU TIME : “+ this.cpuTime);
this.cpuProduct = product;
}

CPU vs GPU — Comparação de Desempenho

CPU vs GPU — Tempo de execução

Como você pode ver claramente, a programação de GPU levou apenas 799ms para os cálculos, enquanto a CPU levou 7511ms, o que é quase 10 vezes maior.

CPU vs GPU

Primeiro, tentei com tamanhos menores de matriz, e notei que a CPU tinha levado menos tempo que a GPU. Por exemplo, quando reduzi o tamanho do array para 10 elementos, a CPU só levou 0,14ms enquanto a GPU levou 108 ms.

conclusão

Comentários

Postagens mais visitadas deste blog

Jogo da velha em C

Calcular distancia entre dois pontos google maps

Java Web Start