React 与 WebGPU:探索下一代图形接口在 React 数据可视化组件中的高性能集成

news2026/4/30 21:59:00
各位听众朋友们大家好欢迎来到这场关于“如何让 React 和 WebGPU 谈一场轰轰烈烈的恋爱”的技术讲座。我是你们的老朋友一个既喜欢在 React 里面写 Hooks又喜欢在 GPU 里写 Shader 的资深程序员。今天我们不聊那些虚头巴脑的“架构设计模式”或者“高内聚低耦合”咱们直接上干货。我们要聊的是 WebGPU——这个 WebGL 2.0 的“大哥哥”这个让无数前端工程师既爱又恨的下一代图形接口。为什么我们要聊这个因为现在的 WebGL 就像是一个穿着紧身衣的胖子虽然能干活但稍微一跑数据量大点的可视化比如一百万个点的粒子系统它就开始喘粗气甚至把浏览器卡死。WebGPU 就像是给它换了一套健美教练训练出来的肌肉不仅身材好还能抗揍。那么React 怎么和 WebGPU 搞在一起React 的声明式 UI 和 WebGPU 的命令式渲染之间到底有没有第三条路今天我们就来探索一下。第一部分WebGPU那个被 WebGL 憋坏了的“大哥哥”首先咱们得搞清楚 WebGPU 到底是个啥。如果你觉得 WebGL 是 2011 年的老古董那 WebGPU 就是 2024 年的“新新人类”。WebGL 的设计初衷是为了让网页能跑 3D 游戏。为了兼容所有老设备WebGL 被设计得非常“宽容”。它把所有的渲染逻辑都塞进了一个叫“状态机”的笼子里。你想画个三角形好你得先告诉显卡“我要画三角形了”然后把颜色设成红色再把混合模式设成加法。一旦状态乱了你就得重新设置。这就像你做菜切个菜都要先开火、再放油、再关火、再放菜流程繁琐得让人想报警。而 WebGPU 呢它直接跟显卡的底层 API比如 Vulkan、Metal、DirectX 12对话。它放弃了那些繁琐的状态机换成了更现代的“命令缓冲区”模式。简单来说WebGPU 更像是直接跟显卡说话“嘿我有一堆指令你按顺序执行就行别问我要不要开火直接干”对于数据可视化来说这简直是福音。数据可视化最怕什么最怕数据量大WebGL 处理 10 万个点可能还行但到了 100 万个点它就开始掉帧。WebGPU 因为可以直接利用 GPU 的并行计算能力处理 1000 万个点就像处理 1000 个点一样轻松。但是WebGPU 也有个毛病它很难。它的 API 名字长得像是在念咒语Shader 语言WGSL虽然看着像 TypeScript但写起来比 TypeScript 还要疯狂。第二部分React 的“声明式”与 WebGPU 的“命令式”的碰撞React 的核心哲学是“声明式”。你告诉 React “我想看到红色的按钮”React 会自动决定怎么渲染。而 WebGPU 是“命令式”的。你必须手动告诉 GPU“创建这个缓冲区”、“上传这个数据”、“运行这个 Shader”。这两者怎么结合这就像是你想用 React 做一个动态图表但你又想亲自去控制 GPU 的每一个像素。如果我们直接在 React 里写ctx.draw()那 React 就变成了一个普通的库失去了它强大的生命周期管理能力。我们需要一种模式让 React 负责“状态管理”和“生命周期”而把“渲染逻辑”交给 WebGPU。这里我给大家介绍一个经典的架构模式Render Props渲染属性模式。代码示例Hello World别怕咱们先来个最简单的例子。假设我们想在屏幕中间画一个旋转的三角形。import React, { useEffect, useRef } from react; // 假设我们有一个简单的 WebGPU 初始化 Hook // 这个 Hook 负责搞定那些繁琐的 Adapter、Device、Context 初始化 function useWebGPU() { const canvasRef useRef(null); useEffect(() { if (!navigator.gpu) { console.error(你的浏览器不支持 WebGPU请换个 Chrome Canary 或者 Edge Edge); return; } // 1. 找房东要钥匙 navigator.gpu.requestAdapter().then(adapter { // 2. 拿到钥匙开门 adapter.requestDevice().then(device { // 3. 获取 Canvas 上下文 const context canvasRef.current.getContext(webgpu); // 4. 配置上下文格式 const format navigator.gpu.getPreferredCanvasFormat(); context.configure({ device: device, format: format, alphaMode: premultiplied, }); // 5. 创建一个 Pipeline管道 // 管道是 WebGPU 的灵魂就像 React 的组件一样 const pipeline device.createRenderPipeline({ layout: auto, vertex: { module: device.createShaderModule({ code: vertexShaderCode }), entryPoint: main, }, fragment: { module: device.createShaderModule({ code: fragmentShaderCode }), entryPoint: main, targets: [{ format: format }], }, primitive: { topology: triangle-list, }, }); // 6. 渲染循环 function frame() { const commandEncoder device.createCommandEncoder(); const textureView context.getCurrentTexture().createView(); const renderPassDescriptor { colorAttachments: [{ view: textureView, clearValue: { r: 0, g: 0, b: 0, a: 1 }, loadOp: clear, storeOp: store, }], }; const passEncoder commandEncoder.beginRenderPass(renderPassDescriptor); passEncoder.setPipeline(pipeline); // 这里我们可以设置 Uniforms比如旋转角度 passEncoder.draw(3); // 画3个顶点的三角形 passEncoder.end(); device.queue.submit([commandEncoder.finish()]); requestAnimationFrame(frame); } frame(); }); }); }, []); return canvasRef; } // 顶点着色器代码 const vertexShaderCode struct Uniforms { mvpMatrix : mat4x4f32, }; binding(0) group(0) varuniform uniforms : Uniforms; struct VertexOutput { builtin(position) Position : vec4f32, location(0) vColor : vec4f32, }; vertex fn main(location(0) position : vec3f32) - VertexOutput { var output : VertexOutput; // 传递位置并乘以 MVP 矩阵 output.Position uniforms.mvpMatrix * vec4f32(position, 1.0); // 假设我们在 JS 里传了颜色数据这里简化处理 output.vColor vec4f32(1.0, 0.0, 0.0, 1.0); return output; } ; // 片元着色器代码 const fragmentShaderCode fragment fn main(location(0) vColor : vec4f32) - location(0) vec4f32 { return vColor; } ; // React 组件 export default function TriangleApp() { const canvasRef useWebGPU(); return ( div style{{ width: 100vw, height: 100vh, background: #000 }} canvas ref{canvasRef} style{{ width: 100%, height: 100% }} / /div ); }看到没这就是 WebGPU 的基本操作。我们在 React 里只需要一个useRef和一个canvas标签。复杂的初始化、Pipeline 创建、渲染循环全部被封装在useWebGPU这个 Hook 里。第三部分数据可视化的核心——渲染百万级粒子光画个三角形有什么意思咱们来做点真东西。数据可视化的痛点通常在于数据量大。比如我们要渲染一个 3D 的地球上面有 100 万个数据点。在 WebGL 里我们通常需要手动管理 VBO顶点缓冲对象还要注意顶点数组的对齐方式。在 WebGPU 里这些概念被抽象成了Buffer和BufferBinding。1. 数据上传不要做“快递员”要做“仓库管理员”React 的数据通常在 CPU 上JavaScript 对象。WebGPU 的数据在 GPU 上。我们需要把数据从 CPU 传到 GPU。这就像你从淘宝买了东西快递员CPU把东西送到你家GPU 显存然后快递员就走了。千万不要每帧都做这件事如果你在requestAnimationFrame的每一帧里都调用device.queue.writeBuffer你的 CPU 会瞬间崩溃因为数据传输是异步的而且非常慢。正确的做法是静态数据一次上传动态数据定期更新。代码示例粒子系统假设我们有一个 React 组件它管理着一组随机的坐标数据。function ParticleSystem() { const canvasRef useRef(null); const deviceRef useRef(null); const pipelineRef useRef(null); const bufferRef useRef(null); // 生成 100 万个随机点的数据 const pointCount 1000000; const positions new Float32Array(pointCount * 3); const colors new Float32Array(pointCount * 4); for (let i 0; i pointCount; i) { positions[i * 3] (Math.random() - 0.5) * 2; // x positions[i * 3 1] (Math.random() - 0.5) * 2; // y positions[i * 3 2] (Math.random() - 0.5) * 2; // z colors[i * 4] Math.random(); // r colors[i * 4 1] Math.random(); // g colors[i * 4 2] Math.random(); // b colors[i * 4 3] 1.0; // a } useEffect(() { // 1. 初始化 WebGPU (同上省略 Adapter/Device 获取逻辑) navigator.gpu.requestAdapter().then(adapter { adapter.requestDevice().then(device { deviceRef.current device; const context canvasRef.current.getContext(webgpu); const format navigator.gpu.getPreferredCanvasFormat(); context.configure({ device, format, alphaMode: premultiplied }); // 2. 创建 Shader (稍微高级一点的 Shader) const shaderCode struct Uniforms { mvpMatrix : mat4x4f32, pointSize : f32, }; binding(0) group(0) varuniform uniforms : Uniforms; struct VertexOutput { builtin(position) Position : vec4f32, location(0) color : vec4f32, }; vertex fn main(location(0) position : vec3f32, location(1) color : vec4f32) - VertexOutput { var output : VertexOutput; output.Position uniforms.mvpMatrix * vec4f32(position, 1.0); output.color color; return output; } ; // 3. 创建 Pipeline const pipeline device.createRenderPipeline({ layout: auto, vertex: { module: device.createShaderModule({ code: shaderCode }), entryPoint: main, }, fragment: { module: device.createShaderModule({ code: fragment fn main(location(0) color : vec4f32) - location(0) vec4f32 { return color; } }), entryPoint: main, targets: [{ format: format }], }, primitive: { topology: point-list }, // 关键点列表模式 }); pipelineRef.current pipeline; // 4. 创建 Buffer 并上传数据 // BufferUsage.VERTEX 表示这是顶点数据 // BufferUsage.COPY_DST 表示我们可以往这个 Buffer 写入数据 const positionBuffer device.createBuffer({ size: positions.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, }); const colorBuffer device.createBuffer({ size: colors.byteLength, usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST, }); // 把 CPU 的数据一次性丢给 GPU device.queue.writeBuffer(positionBuffer, 0, positions); device.queue.writeBuffer(colorBuffer, 0, colors); bufferRef.current { positionBuffer, colorBuffer }; // 5. 渲染循环 function frame() { if (!deviceRef.current || !pipelineRef.current) return; const commandEncoder deviceRef.current.createCommandEncoder(); const textureView context.getCurrentTexture().createView(); const passEncoder commandEncoder.beginRenderPass({ colorAttachments: [{ view: textureView, clearValue: { r: 0, g: 0, b: 0, a: 1 }, loadOp: clear, storeOp: store, }], }); passEncoder.setPipeline(pipelineRef.current); // 绑定 Buffer passEncoder.setVertexBuffer(0, bufferRef.current.positionBuffer); passEncoder.setVertexBuffer(1, bufferRef.current.colorBuffer); // 设置 Uniforms (这里简化实际需要构建矩阵) // passEncoder.setBindGroup(0, ...); // 画点 passEncoder.draw(pointCount); passEncoder.end(); deviceRef.current.queue.submit([commandEncoder.finish()]); requestAnimationFrame(frame); } frame(); }); }); }, []); return ( canvas ref{canvasRef} style{{ width: 100vw, height: 100vh }} / ); }看到了吗我们定义了pointCount为 1,000,000。在 WebGL 里这需要你手动管理索引数组还要注意缓冲区偏移量。而在 WebGPU 里我们只需要passEncoder.draw(pointCount)。它就像是在说“嘿 GPU把这 100 万个点都画出来别问我怎么画的。”这就是 WebGPU 的威力更少的代码更强的性能。第四部分React 状态与 GPU 的同步——那个让人头秃的“脏检查”React 的数据流是单向的State - Render - Virtual DOM - Real DOM。WebGPU 的数据流是CPU Data - GPU Memory - Shader Execution。如果 React 的state变了WebGPU 怎么知道这里有几种策略策略 AReact 只负责“触发”WebGPU 负责“响应”这是最简单的策略。React 的 state 改变 - 触发useEffect- 重新上传数据 - 重新绘制。缺点如果你每秒改变 60 次 state你的 CPU 就得每秒上传 60 次数据。这就像你每隔一秒换一次衣服虽然衣服是新的但你根本没时间出门。策略 B批处理更新React 本身有批处理机制。如果你在同一个事件处理器里修改了 10 个 stateReact 会把它们合并成一次渲染。这对 WebGPU 非常友好。function handleMouseMove(e) { // React 会自动把这三个 state 的变化合并成一次渲染 setPositionX(e.clientX); setPositionY(e.clientY); setRotation(rotation 1); }策略 C动态 Buffer 更新进阶如果你必须实时更新数据比如模拟流体粒子你不能每帧都上传整个 Buffer。你需要使用setSubData或者更高级的机制。WebGPU 提供了BufferUsage.VERTEX | GPUBufferUsage.COPY_DST。我们可以创建一个“脏标记”只有当数据真正改变时才调用writeBuffer。// 伪代码示例 let dirty true; let positions new Float32Array([...]); function updateData(newData) { positions.set(newData); dirty true; // 标记为脏 } function renderLoop() { if (dirty) { device.queue.writeBuffer(buffer, 0, positions); dirty false; } // ... 绘制 }这种模式要求我们编写一些“胶水代码”在 React 的useEffect和 WebGPU 的渲染循环之间建立通信。这其实有点像 Redux 的 Reducer只不过这里的 State 是 BufferReducer 是setSubData。第五部分WGSL Shader——WebGPU 的灵魂WebGPU 的 Shader 语言叫 WGSL (WebGPU Shading Language)。它长得有点像 TypeScript但是更抽象更强调类型安全。在 React 数据可视化中Shader 负责决定数据的“长相”。1. 矩阵运算数据可视化离不开坐标变换。WebGPU 没有内置的矩阵库你需要自己实现一个简单的矩阵乘法。// 简单的 4x4 矩阵乘法 fn mat4_mul(a: mat4x4f32, b: mat4x4f32) - mat4x4f32 { var result: mat4x4f32; for (var i: u32 0u; i 4u; i) { for (var j: u32 0u; j 4u; j) { result[i][j] a[i][0] * b[0][j] a[i][1] * b[1][j] a[i][2] * b[2][j] a[i][3] * b[3][j]; } } return result; }2. 实例化渲染这是处理数据可视化的杀手锏。假设我们要画 100 个柱状图。WebGL 方式你在 CPU 上生成 100 个柱子的顶点数据打包成一个巨大的数组传给 GPU。WebGPU 方式你只定义 1 个柱子的顶点数据。然后在 Shader 里利用builtin(instance_index)来告诉 GPU 当前渲染的是第几个柱子。vertex fn main( location(0) position : vec3f32, // 柱子的形状 builtin(instance_index) instanceIdx : u32 // 当前是第几个柱子 ) - VertexOutput { // 通过 instanceIdx 偏移位置实现实例化 var output : VertexOutput; output.Position vec4f32(position.x f32(instanceIdx) * 0.5, position.y, position.z, 1.0); return output; }在 React 中这意味着我们可以把数据结构设计得非常扁平。比如一个数组[10, 20, 30, 40]我们可以把它看作是 4 个实例的柱状图高度。这种数据结构在 React 的map函数中非常容易生成传给 WebGPU 后GPU 也能高效处理。第六部分调试——WebGPU 的“地狱模式”如果你觉得 WebGL 的调试很难那你还没见过 WebGPU。WebGPU 的错误代码通常是十六进制的比如0x824。Chrome 的开发者工具现在支持 WebGPU 调试但这依然是一个黑盒。1. Shader 编译错误WGSL 的语法非常严格。如果你少了一个分号或者类型不匹配WebGPU 会直接拒绝编译你的画布会变黑控制台会报错。技巧使用 Chrome 的--enable-featuresVulkan标志启动浏览器这能更好地捕获错误。2. BindGroup 错误这是最常见的问题。WebGPU 使用BindGroup来把数据传递给 Shader。如果你在 Shader 里声明了binding(0)但你忘记在 JS 里创建对应的bindGroup或者bindGroupLayout不匹配渲染就会失败。// 错误示例Shader 要 binding(0)JS 里却传了 binding(1) passEncoder.setBindGroup(0, myBindGroup);React 的开发者工具现在可以帮你查看组件树但很难帮你查看 GPU 的内部状态。所以写 Shader 时请务必保持清醒的头脑。第七部分React 库的诞生——让 WebGPU 变得“React 化”既然手动集成这么麻烦社区里已经出现了一些库试图把 WebGPU 包装成 React 组件。比如react-three/webgpu虽然它更多是基于 Three.js 的封装但思想类似或者更底层的webgpu/wgsl。我们可以想象一个理想的 React WebGPU 组件库是这样的function HeatmapChart({ data }) { return ( WebGPURender Mesh Shader vs{vertexShader} fs{fragmentShader} uniforms{{ data: data, // 自动处理 Buffer 上传 time: useTime() // 自动获取时间 Uniform }} / /Mesh /WebGPURender ); }在这个理想世界里React 负责管理数据WebGPU 负责渲染。开发者只需要写 Shader或者使用预设的 Shader不需要关心 Buffer 的创建和销毁。第八部分性能优化的终极奥义——避免“CPU-GPU 同步”React 是 CPU 密集型的虽然 React 本身很快但数据转换可能很慢WebGPU 是 GPU 密集型的。性能瓶颈通常出现在CPU 和 GPU 的同步上。当你调用device.queue.writeBuffer时CPU 会把数据发送给 GPU。如果 GPU 正在忙比如正在渲染上一帧CPU 就得等待。这叫“Stall”。为了解决这个问题WebGPU 允许我们创建“双缓冲”或者使用“异步队列”。在 React 中我们不应该在渲染循环里做大量的数据转换。我们应该在useEffect里做数据转换或者在useMemo里缓存转换后的数据。React 开发者的黄金法则不要在render函数里调用device.queue.writeBuffer。render函数在 React 中可能会被频繁调用这会导致严重的性能问题。使用useMemo缓存 Buffer 数据。只有当数据真正变化时才更新 Buffer。使用requestAnimationFrame进行渲染循环而不是 React 的useEffect。requestAnimationFrame能保证渲染频率与显示器刷新率同步通常是 60Hz 或 144Hz并且能避开 React 的调度延迟。第九部分未来展望WebGPU 还在发展中但它的潜力是巨大的。对于数据可视化来说WebGPU 带来的不仅仅是性能的提升还有可能性。实时流体模拟以前只能做静态的热力图现在可以实时模拟水流、烟雾、火苗。复杂地形渲染带有光照、阴影、法线贴图的 3D 地图可以流畅地在浏览器中运行。VR/AR 可视化WebGPU 是原生支持 WebXR 的这意味着我们可以用 React 创建沉浸式的数据大屏。虽然目前 WebGPU 的 API 还比较原始学习曲线陡峭但在 React 的加持下它正在变得越来越友好。我们可以期待未来会有更多基于 WebGPU 的可视化库出现比如Recharts的下一代或者D3.js的 WebGPU 版本。结语虽然你说不要总结但作为讲座总要收个尾好了各位听众今天的讲座就到这里。我们聊了 React 的声明式之美也聊了 WebGPU 的命令式之力。我们看到了如何用 React 的 Hooks 来管理 WebGPU 的生命周期如何用 Buffer 来传输数据如何用 Shader 来决定视觉。WebGPU 并不是 React 的替代品它是 React 强大的左膀右臂。当你面对那些动辄千万级的数据点当你需要构建一个 3D 的、实时的、高性能的数据大屏时React 可能会感到吃力但 WebGPU 会告诉你“交给我吧这对我来说只是小菜一碟。”记住不要害怕 Shader不要害怕 Buffer。代码写得多了你就能理解 GPU 的语言。就像你学会了 React你也能学会 WebGPU。最后祝大家在 WebGPU 的世界里玩得开心渲染出最酷炫的数据可视化作品谢谢大家

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…