前端神经网络入门(二):如何利用 WebGPU 进行数值计算,实现大规模数据的计算加速?- 边读边按下F12跑代码吧

在 Web 应用开发中,JavaScript 是前端开发者们最常用的语言。然而,当面对大规模数据处理和计算任务时,JavaScript 在浏览器中的执行往往会受到诸多性能瓶颈的限制。幸运的是,WebGPU 的出现,为我们提供了在前端实现高性能计算的新途径。本文将首先探讨 JavaScript 在执行大规模计算方面的劣势,然后介绍如何利用 WebGPU 进行计算加速,以及它带来的性能提升。最后,我们将以一个例子来演示如何在浏览器中利用 WebGPU 进行大规模数值计算。

除了webGPU,还有一个提升计算性能的WASM技术栈,感兴趣的可以了解,或许后续我会再谈到

JavaScript 在大规模计算中的劣势

JavaScript 是一门解释型语言,主要用于处理前端的交互逻辑,如 DOM 操作、事件处理和 UI 更新等。尽管近年来 JavaScript 引擎得到了极大的优化(如 V8 引擎的 JIT 编译),但在面对大规模数值计算时,JavaScript 依然存在以下劣势:

  1. 单线程执行:JavaScript 在浏览器环境中通常是单线程的,尽管 Web Workers 提供了一些多线程的支持,但对于大量需要并行处理的数值计算,性能依旧受到限制。
  2. 计算效率低:JavaScript 本质上并不是为高效执行数值计算而设计的。它的动态类型和内存管理机制导致处理浮点数运算和矩阵操作时效率较低。
  3. 缺乏硬件加速:JavaScript 在浏览器中运行时,通常只能依靠 CPU,无法直接利用 GPU 的强大并行处理能力来加速大规模数值运算。

在这样的情况下,大规模数据的处理和训练神经网络通常需要依赖后端的计算能力,例如通过 Web API 将数据发送到服务器,由服务器使用 GPU 或其他高性能计算设备完成后再将结果返回。这种模式存在明显的 网络延迟隐私保护 问题。

WebGPU 引入与计算加速的可行性

WebGPU 是一项现代的 Web API,它使得开发者能够在浏览器中直接访问 GPU,以进行图形渲染和 高性能数值计算。相比于 WebGL,WebGPU 提供了更底层和更灵活的控制能力,并允许更直接地访问 GPU,执行包括矩阵运算、机器学习推断在内的大量并行计算任务。

WebGPU 的浏览器兼容性

目前,WebGPU 还在发展中,并没有在所有主流浏览器中全面支持。以下是一些关于兼容性的情况:

  • ChromeEdge:这两个浏览器提供了对 WebGPU 的支持,但需要在某些情况下通过实验性设置开启。
  • Firefox:WebGPU 的支持正在开发中,部分功能可能在实验性版本中使用。
  • Safari:Apple 也在积极推进对 WebGPU 的支持,可以在最新的版本中体验到。
    在这里插入图片描述
WebGPU 带来的效果提升

与 JavaScript 使用 CPU 进行运算相比,WebGPU 可以利用 GPU 的 并行计算能力,极大地加快大规模数值运算的速度。GPU 可以同时执行上千个小型计算任务,对于矩阵相乘、向量运算等高度并行的计算任务,性能提升可以达到数十倍甚至上百倍。

利用 WebGPU 的通用计算能力,可以将以前需要后端支持的复杂任务(如神经网络推断、实时数据分析等)转移到前端,使得应用可以更快速响应用户的输入,并且无需将数据传到服务器,保护用户隐私。

实战示例:使用 WebGPU 进行数值计算

为了让大家对 WebGPU 如何进行数值计算有更清晰的认识,我们将以 向量相加 作为例子,演示如何在前端使用 WebGPU 实现 GPU 加速的数值计算。

因为不需要外部依赖,所以按F12打开开发者工具,复制粘贴代码测试吧~

示例:向量相加

我们将实现两个长度为 3 的向量 [1, 2, 3][4, 5, 6] 相加,预期结果为 [5, 7, 9]

1. 初始化 WebGPU

首先,我们需要获取 GPU 适配器和设备:

async function initWebGPU() {if (!navigator.gpu) {console.error("WebGPU is not supported in this browser.");return;}const adapter = await navigator.gpu.requestAdapter();const device = await adapter.requestDevice();return device;
}
2. 创建缓冲区

接下来,我们创建 GPU 缓冲区,用于存储输入和输出数据:

async function createBuffers(device) {const a = new Float32Array([1, 2, 3]);const b = new Float32Array([4, 5, 6]);const result = new Float32Array(a.length);const aBuffer = device.createBuffer({size: a.byteLength,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,mappedAtCreation: true});new Float32Array(aBuffer.getMappedRange()).set(a);aBuffer.unmap();const bBuffer = device.createBuffer({size: b.byteLength,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,mappedAtCreation: true});new Float32Array(bBuffer.getMappedRange()).set(b);bBuffer.unmap();const resultBuffer = device.createBuffer({size: result.byteLength,usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC,});return { aBuffer, bBuffer, resultBuffer, resultLength: result.length };
}
3. 编写计算着色器

接着,我们编写一个简单的 WGSL 着色器,用于执行向量相加的操作:

const shaderCode = `@group(0) @binding(0) var<storage, read> a: array<f32>;@group(0) @binding(1) var<storage, read> b: array<f32>;@group(0) @binding(2) var<storage, read_write> result: array<f32>;@compute @workgroup_size(64)fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {let index = global_id.x;// 假设数组的长度为 3,你可以传递更大的值或者作为一个变量处理if (index < 3u) {result[index] = a[index] + b[index];}}
`;
4. 创建计算管线和绑定组

计算管线用于定义计算任务的执行方式,绑定组用于绑定缓冲区:

async function createPipeline(device, shaderCode) {const shaderModule = device.createShaderModule({code: shaderCode});const computePipeline = device.createComputePipeline({layout: "auto",compute: {module: shaderModule,entryPoint: "main"}});return computePipeline;
}async function createBindGroup(device, pipeline, buffers) {return device.createBindGroup({layout: pipeline.getBindGroupLayout(0),entries: [{ binding: 0, resource: { buffer: buffers.aBuffer } },{ binding: 1, resource: { buffer: buffers.bBuffer } },{ binding: 2, resource: { buffer: buffers.resultBuffer } }]});
}
5. 执行计算任务并读取结果

最后,我们执行计算任务并将结果读取出来:

async function runComputeTask(device, pipeline, bindGroup, resultBuffer, resultLength) {const commandEncoder = device.createCommandEncoder();const passEncoder = commandEncoder.beginComputePass();passEncoder.setPipeline(pipeline);passEncoder.setBindGroup(0, bindGroup);passEncoder.dispatchWorkgroups(Math.ceil(resultLength / 64));passEncoder.end();const gpuReadBuffer = device.createBuffer({size: resultLength * Float32Array.BYTES_PER_ELEMENT,usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ});commandEncoder.copyBufferToBuffer(resultBuffer, 0, gpuReadBuffer, 0, resultLength * Float32Array.BYTES_PER_ELEMENT);const commandBuffer = commandEncoder.finish();device.queue.submit([commandBuffer]);await gpuReadBuffer.mapAsync(GPUMapMode.READ);const arrayBuffer = gpuReadBuffer.getMappedRange();const resultArray = new Float32Array(arrayBuffer);console.log("Result:", Array.from(resultArray));gpuReadBuffer.unmap();
}(async () => {const device = await initWebGPU();const buffers = await createBuffers(device);const pipeline = await createPipeline(device, shaderCode);const bindGroup = await createBindGroup(device, pipeline, buffers);await runComputeTask(device, pipeline, bindGroup, buffers.resultBuffer, buffers.resultLength);
})();

运行结果

Result: [5, 7, 9]

在这里插入图片描述

总结

WebGPU 为前端带来了利用 GPU 进行高性能计算的可能性,使得 JavaScript 不再局限于处理简单的 UI 和业务逻辑,而是能够执行更复杂的数值计算和大规模数据处理任务。与传统的 JavaScript 计算方式相比,WebGPU 在大规模并行任务(如矩阵运算、图像处理和机器学习)上提供了显著的性能提升。

通过本文的示例代码,开发者可以初步了解如何使用 WebGPU 进行数值计算,将大规模计算任务从后端转移到前端,不仅能提高应用的响应速度,还能保护用户数据隐私。随着浏览器对 WebGPU 的支持逐渐成熟,前端开发者们将能用它来开发出更高效、更智能的 Web 应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/60794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新手教学系列——善用 VSCode 工作区,让开发更高效

引言 作为一名开发者,你是否曾经在项目中频繁地切换不同文件夹,打开无数个 VSCode 窗口?特别是当你同时参与多个项目或者处理多个模块时,这种情况更是家常便饭。很快,你的任务栏上挤满了 VSCode 的小图标,切换起来手忙脚乱,工作效率直线下降。这时候,你可能会问:“有…

Oracle故障处理:ora-12514 与 ora-28547

目录 项目场景 问题分析 问题总结 项目场景 现场同事求助说&#xff1a;有个刚刚部署在Windows上的Oracle11gR2数据库&#xff08;单机单实例&#xff09;&#xff0c;使用PLSQL工具连接不上。帮忙查看后&#xff0c;发现未装Oracle client&#xff0c;指导其安装完Oracle客…

Kafka基础知识学习

Kafka概念 一、核心组件对照表 组件定义主要功能特点BrokerKafka集群中的服务器节点存储消息、处理请求、管理分区唯一ID&#xff0c;可能成为ControllerTopic消息的逻辑分类单元消息分类、存储组织包含多个Partition&#xff0c;类似数据库表PartitionTopic的物理分片并行处…

【miniMax开放平台-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被机器执行自动化程序攻击&#xff0c;存在如下风险&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露&#xff0c;不符合国家等级保护的要求。短信盗刷带来的拒绝服务风险 &#xff0c;造成用户无法登陆、注册&#xff0c;大量收到垃圾短信的…

PC上浏览器是如何查询DNS 缓存的呢?

通过 ipconfig /displaydns 的显示结果可以获取本机的 DNS 缓存信息&#xff0c;那么浏览器是如何获取本机的 DNS 缓存。 答案是&#xff1a;浏览器获取本机的 DNS 缓存主要是通过操作系统提供的接口来获取&#xff0c;。 具体的获取途径如下&#xff1a; 先查询自身缓存&am…

26-ES集群搭建、身份认证配置

虚机搭建 添加es用户 elasticsearch 默认不允许root用户启动&#xff0c;所以需要创建es用户 useradd elasticsearch passwd elasticsearch 解压安装包 #解压es tar -xvzf elasticsearch-7.14.2-linux-x86_64.tar.gz 将文件夹赋予es用户权限 #将文件夹赋予es用户权限 sud…

BuyPass SSL证书:申请免费可用多域名SSL证书6个月180天

目录 一、前沿 二、条件 三、申请流程 四、注意事项 五、总结 一、前沿 找到一个6个月180天的免费证书&#xff0c;目前 BuyPass 提供了类似ZerSSL 等基于 ACME/Certbot 的证书自动签发服务 - BuyPass GO Free SSL&#xff0c;完全免费&#xff0c;只支持单域名、多域名&am…

OpenHarmony的公共事件

OpenHarmony的公共事件 公共事件简介 CES&#xff08;Common Event Service&#xff0c;公共事件服务&#xff09;为应用程序提供订阅、发布、退订公共事件的能力。 公共事件分类 公共事件从系统角度可分为&#xff1a;系统公共事件和自定义公共事件。 系统公共事件&#…

【AlphaFold3】开源本地的安装及使用

文章目录 安装安装DockerInstalling Docker on Host启用Rootless Docker 安装 GPU 支持安装 NVIDIA 驱动程序安装 NVIDIA 对 Docker 的支持 获取 AlphaFold 3 源代码获取基因数据库获取模型参数构建将运行 AlphaFold 3 的 Docker 容器 参考 AlphaFold3: https://github.com/goo…

npm list -g --depth=0(用来列出全局安装的所有 npm 软件包而不显示它们的依赖项)

您提供的命令 npm list -g --depth0 是在 Node Package Manager (npm) 的上下文中使用的&#xff0c;用来列出全局安装的所有 npm 软件包而不显示它们的依赖项。 这是它的运作方式&#xff1a; npm list -g --depth0-g: 指定列表应包括全局安装的软件包。--depth0: 限制树形结…

React状态管理之Redux

React状态管理之Redux 在React应用中&#xff0c;状态管理是一个至关重要的概念。随着应用规模的扩大&#xff0c;组件之间的状态共享和更新变得愈发复杂。Redux作为一个专门用于JavaScript应用&#xff08;尤其是React应用&#xff09;的状态管理库&#xff0c;提供了一种可预…

Spring Boot框架:电商系统的技术革新

4 系统设计 网上商城系统的设计方案比如功能框架的设计&#xff0c;比如数据库的设计的好坏也就决定了该系统在开发层面是否高效&#xff0c;以及在系统维护层面是否容易维护和升级&#xff0c;因为在系统实现阶段是需要考虑用户的所有需求&#xff0c;要是在设计阶段没有经过全…

layui.all.js:2 Uncaught Error: Syntax error, unrecognized expression

报错内容&#xff1a; layui.all.js:2 Uncaught Error: Syntax error, unrecognized expression: input[name"image1UploadTime"language] 错误代码&#xff1a; $(input[name"imagejUploadTime"language]).val(currentDateTime); 因为 language 是个变…

Scala的set

//Set的特点&#xff1a;唯一&#xff08;元素不相同&#xff09;&#xff1b;无序 case class Book(var bookName:String,var author:String,var price:Double){} object test27 {def main(args: Array[String]): Unit {//定义一个可变setval set1 scala.collection.mutable…

【数据分享】中国对外投资合作发展报告(2013-2023)

数据介绍 绪 论............................................................................................................................. 1 对外投资合作高质量发展迈出新步伐................................................................... 2 第一篇 发…

【深度学习】LSTM、BiLSTM详解

文章目录 1. LSTM简介&#xff1a;2. LSTM结构图&#xff1a;3. 单层LSTM详解4. 双层LSTM详解5. BiLSTM6. Pytorch实现LSTM示例7. nn.LSTM参数详解 1. LSTM简介&#xff1a; LSTM是一种循环神经网络&#xff0c;它可以处理和预测时间序列中间隔和延迟相对较长的重要事件。LSTM通…

leetcode hot100【LeetCode 236.二叉树的最近公共祖先】java实现

LeetCode 236.二叉树的最近公共祖先 题目描述 给定一个二叉树, 找到该树中两个给定节点的最近公共祖先。 节点可以表示为它在树中的路径&#xff0c;其中路径的第一个节点是根节点&#xff0c;每个后续节点是其父节点的直接子节点。 示例 1: 输入: root [3,5,1,6,2,0,8,n…

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

跟李笑来学美式俚语(Most Common American Idioms): Part 02

Most Common American Idioms: Part 02 前言 本文是学习李笑来的Most Common American Idioms这本书的学习笔记&#xff0c;自用。 Github仓库链接&#xff1a;https://github.com/xiaolai/most-common-american-idioms 使用方法: 直接下载下来&#xff08;或者clone到本地…

Molecular signatures database (MSigDB) 3.0

文献翻译和解读&#xff08;解读在最后&#xff09; 摘要 动机&#xff1a; 良好注释的基因集代表了生物学过程的全貌&#xff0c;对于大规模基因组数据的有意义和深入解读至关重要。分子特征数据库&#xff08;MSigDB&#xff09;是最广泛使用的此类基因集资源库之一。 结果…