webassembly学习

news2024/12/24 20:31:59

webassembly

  • webassembly学习
    • 基本理论
      • webassembly介绍
        • wasm介绍
          • 基本信息
          • wasm会替换javascript么
          • ASM.js(wasm的前身)
          • 将 WebAssembly 作为编程语言的一种尝试
          • wasm应用场景
          • wasm运行原理
          • 周边生态
          • WASI 操作系统接口
        • wasi介绍
        • wasm+wasi(服务端)
          • wasm runtime对比(虚拟机)
          • wasmedge
          • wasmtime
          • wasmer
          • wamr
          • wavm
      • emscripten教程
        • TODO
      • 模型推理
        • paddlejs
          • paddlejs小程序跑模型
        • MNN.js
        • NCNN
        • tfjs
        • openvinojs
        • onnxruntimejs
      • wasm+wasi替代docker,服务端
      • webgl
      • 部分功能实现
        • SQL

webassembly学习

基本理论

webassembly介绍

产生的原因:希望将一些非javascript的代码运行在浏览器上,避免重新开发的工作量。
webassembly诞生
在这里插入图片描述

wasm介绍

系统学习webassembly
webassembly实现细节
为什么webassembly是web的未来?

基本信息
  • wasm 是一个可移植、体积小、加载快并且兼容 Web 的全新格式.
  • wasm 代码格式: - .wasm - wasm二进制格式
  • .wabt - web assembly text format,编译结果的文本格式,用于调试
  • 通过wabt可以实现wasm和wabt格式的转换
wasm会替换javascript么

wasm不会替换javascript,可以帮助javascript解决一些无法解决的问题

  • 解除对不同浏览器环境的强依赖

如今现代前端开发对webpack、babel、polyfill的依赖都非常重,编译后动辄就是几兆几兆的大小,当一个业务非常复杂之后,不得不采用各种各样的手段来做优化。另外,浏览器的安全也是一个大问题。

  • 弱类型还是强类型

尽管我们有TypeScript,然而它只能在编译阶段帮我们做好类型的校验,除此之外,如 + 运算符、null == undefined 等诡异结果也是JavaScript种种难以克服的通病。

  • WASM 的设计初衷就可以梳理为以下几点:
    1)最大程度的复用现有的底层语言生态,如 C/C++ 在游戏开发、编译器设计等方面的积淀
    2)在 Web、Node.js 或其他 WASM runtime 获得近乎于原生的性能,也就是可以让浏览器也能跑大型游戏、图像剪辑等应用
    3)还有最大程度的兼容 Web、保证安全
    4)同时在开发上(如果需要开发)易于读写和可调试,这一点 AssemblyScript 走得更远
    所以从初衷出发,WebAssembly 的作用更适合下面这张图:
    在这里插入图片描述

WASM 桥接各种系统编程语言的生态,进一步补齐了 Web 开发生态之外,还为 JS 提供性能的补充,正是 Web 发展至今所缺失的重要的一块版图。

一种直接运行在web前端,一种运行在后端服务,通过wasm runtime来启动

ASM.js(wasm的前身)

ASM.js仍然是被编译出来的,书写的C/C++代码经过静态编译后,会输出为一段特定的JavaScript代码,浏览器引擎在运行这段代码时,会做特别的优化。
阮一峰的入门

javascript是动态语言,当多次调用同一个函数,参数类型发生变化后,需要重新进行parser-compile。而Asm.js是静态编译语言,会更快,去除了Javascript垃圾回收机制。详细可看:
为什么webassembly是web的未来?

将 WebAssembly 作为编程语言的一种尝试

因为上述的二进制和文本格式都不适合编码,所以不适合将 WASM 作为一门可正常开发的语言。

为了突破这个限制,AssemblyScript[6] 走到台前,AssemblyScript 是 TypeScript 的一种变体,为 JavaScript 添加了 WebAssembly 类型[7] , 可以使用 Binaryen[8] 将其编译成 WebAssembly。

目前使用 AssemblyScript 构建的应用生态已经初具繁荣,目前在区块链、构建工具、编辑器、模拟器、游戏、图形编辑工具、库、IoT、测试工具等方面都有大量使用 AssemblyScript 构建的产物:https://www.assemblyscript.org/built-with-assemblyscript.html#games

wasm应用场景

在这里插入图片描述

wasm运行原理
  • 如何运行的
    一般来说,一个可运行的程序分为两部分,即数据 + 指令,而WASM是基于堆栈机模型和虚拟指令集来实现程序的运行,堆栈机模型是常见的内存管理结构,将数据和操作符压入栈中并弹出逐次执行,而虚拟指令集(V-ISA)则可以认为是对平台无关的一系列自定义操作符(如JVM),相对的,物理指令集(ISA)则是强依赖物理系统的(如Intel的x86-64)。
    我们把浏览器比作JVM虚拟机,WASM二进制编码比作Java字节码,是不是就能很快明白为什么浏览器上可以运行WASM了?
  • 剖析WASM文件结构
    首先在组织结构上,WASM会把特定功能或者有相关联的代码放进一个特定的区块(Section)中,而这些区块(Section)组成了程序。
    1)TypeSection
    存放与“类型”相关的内容,主要是“函数签名”,即返回值与参数值。
    2)StartSection
    在模块初始化完成后,被首先调用的函数,可以近似理解为main函数
    3)GlobalSection
    顾名思义,存放了程序相关的全局变量,可能是程序自定义的数据,也可能是流程相关的
    4)CustomSection
    可以用作将来自定义扩展功能的实现
    5)ImportSection
    从宿主环境中,我们可以向WASM模块导入各式各样的数据,换句话说,通过这个Section我们可以实现数据或代码的共享
    6)ExportSection
    同理,既然可以导入,我们也可以导出数据和方法
    7)FunctionSection
    这里存储的是函数类型,与TypeSection一一对应
    8)CodeSection
    这里存储的是函数具体代码,与FunctionSection一一对应
    9)TableSection、ElementSection
    Table存放了函数指针的元信息,Element则是对应Table的具体内容,关于Table的概念可以参考这篇文章:https://zhuanlan.zhihu.com/p/28222049
    10)MemorySection、DataSection
    同上,Memory描述了使用内存的基本情况,Data则是对应具体的实际内容
    wasm以 asm这个字符串的二进制编码开头,随后跟上版本号。
  • 基本数据类型
    1)无符号整数
    WASM支持三种非负整数类型: uint8、uint16、uint32,后面的数字表示占用了多少个bit
    2)可变长无符号整数
    WASM支持三种可变长非负整数类型: varuint1, varuint7, varuint32,所谓可变长的意思是会根据具体数据大小决定使用多少bit,后面的数字表示最大可占用多少个bit
    3)可变长有符号整数
    同上,这里允许负数的出现,这里支持varint7, varint32, varint64三种类型
    4)浮点数
    这里同JS,采用IEEE-754方案,单精度为32位
周边生态
  • 编译工具
    Emscripten、LLVM、Binaryen

  • WAT 使WASM更加可读
    通常来说,WASM二进制文件是不可读的,WebAssembly Text Format(WAT)是另外一种输出格式,以类文本的方式展示输出,我们可以近似的理解为与二进制等价的汇编语言,或者说就是WASM的source-map。
    另外,Flat-WAT是经过优化后的WAT格式,我们可以一张图比较三者输出:
    在这里插入图片描述
    现在社区已经有成熟的转换工具,如wasm2wat,wat2wasm等,我们可以在一个名为WABT(WebAssembly Binary Toolkit)的工具集中找到。

WASI 操作系统接口

wasi介绍

WASI是一个新的API体系, 由Wasmtime项目设计, 目的是为WASM设计一套引擎无关(engine-indepent), 面向非Web系统(non-Web system-oriented)的API标准. 目前, WASI核心API(WASI Core)在做覆盖文件,网络等等模块的API, 但这些实现都是刚刚开始实现, 离实用还是有很长路要走。

 本质让wasm可以在非web系统上运行,把Wasm模块放进Runtime提供的沙箱中运行,Runtime可以限制模块的对于操作系统的访问,为其提供有限的文件系统访问等。而Runtime可以被设计成跨平台的,我们可以在Linux/Windows/MacOS/嵌入式等平台上运行同一个Wasm模块。这就相当于我们有了跨平台且安全的二进制执行方法。

wasm+wasi(服务端)

运行在服务端,类似docker
场景:对于需要频繁启动和停止的场景,会更有优势,服务端docker一旦启动,资源就会一直占用,对于需要高速响应,但是请求却不是很持续。
wasm云原生

wasm runtime对比(虚拟机)

参考资料:
四种主流wasm

在这里插入图片描述

对比
在这里插入图片描述

wasmedge

wasmedgr

wasmtime

WASMTIME是字节码联盟主推的一个WASM虚拟机,既可以作为一个CLI,也可以被嵌入到其他应用系统中,如IoT或者云原生
wasmtime编译cpython
wasmtime

wasmer

这是独立于字节码联盟,并努力构建自己生态的社区推出的产品,特点是支持在更多的编程语言运行WASM实例,并有自己的包管理平台Wapm
wasmer

wamr

同样是字节码联盟旗下的,更偏向于芯片场景的虚拟机,如它的名字所示,体积非常小,起步速度只要100微秒,内存耗费最低只需100KB
wamr

wavm

wavm
WAVM是WebAssembly虚拟机,设计用于非Web应用程序。
特点

  • 快速:WAVM使用LLVM将WebAssembly代码编译为具有接近本机性能的机器代码。在某些情况下,它甚至可以胜过本机性能,这要归功于它能够生成针对运行代码的确切CPU进行了调整的机器代码。
  • 安全:WAVM阻止WebAssembly代码访问WebAssembly虚拟机*之外的状态,或调用未与WebAssembly模块明确链接的本机代码。
https://github.com/WAVM/WAVM
wavm run helloworld.wast
wavm run zlib.wasm
wavm run trap.wast
wavm run echo.wast "Hello, world!"
wavm run helloworld.wast | wavm run tee.wast
wavm run --enable simd blake2b.wast

emscripten教程

参考资料:
emscripten中文
emscriten英文

TODO

模型推理

paddlejs

paddlejs垃圾分类
paddlejs

paddlejs小程序跑模型
  • 第一步:准备一个paddlepaddle模型
    模型使用的是链接中的模型:
    导出的paddle模型
  • 第二步:模型转换
pip install paddlejsconverter

paddlejsconverter --modelPath=./model.pdmodel --paramPath=./model.pdiparams --outputDir=./ --useGPUOpt=True

paddle导出的模型转换后,会报错,issue有人提出,等待解决:

webgl createProgram: conv2d -- Error: Error: compile: ERROR: 0:186: 'undefined' : undeclared identifier
ERROR: 0:186: '' : boolean expression expected

先使用:
转换好的模型

  • 第三步:准备微信小程序环境
    工程可以直接拉大佬的代码:小程序工程。以下代码只是重要部分,不全。
    1)下载微信小程序开发工具:
    微信小程序
    2)新建项目, appID需要注册,测试号使用不是特别方便,需要用申请到的appid创建项目,且选择不使用云开发 。
    微信小程序账号申请
    如果新建项目时用的游客,可通过微信小程序开发工具(详情–>基本信息修改appid)
    3)添加paddlejs插件。位置:先登录微信公众号平台,设置–>第三方设置–>插件管理–>添加插件,搜索:wx7138a7bb793608c3.
    添加这个插件是为了给appid账号授权paddlejs。
    4)在小程序的app.json 中声明插件的provider(appid)& version(指定版本号)
{
...
"plugins": {
 "paddlejs-plugin": {
   "version": "2.0.1",
   "provider": "wx7138a7bb793608c3"
 }
}
...
}

5)进入小程序项目根目录(可以通过右键,通过资源管理器打开进入或者知道文件创建的路径)
在这里插入图片描述
6)使用npm init -yes 创建初始化,此时会出现一个package.json(如果没有npm需要去安装nodejs)。
7)使用npm包引入@paddlejs/paddlejs-core与@paddlejs/paddlejs-backend-webgl,具体如下
在package.json中添加或修改如下

{

“dependencies”: {
“@paddlejs/paddlejs-backend-webgl”: “^1.0.7”,
“@paddlejs/paddlejs-core”: “^2.0.7”
}
}

回到小程序根目录,执行npm i。
8)使用小程序开发者工具,点击 工具-》构建npm!!!
同时关闭合法域名校验(右边详情 -》 本地设置 -》 不校验合法域名…)!!!
在这里插入图片描述
在这里插入图片描述
到这一步,基本上环境是搭建好了,准备使用

9)在app.js或在小程序page的js文件中引入 @paddlejs/paddlejs-core、@paddlejs/paddlejs-backend-webgl 并初始化

import * as paddlejs from '@paddlejs/paddlejs-core';
import '@paddlejs/paddlejs-backend-webgl';

const plugin = requirePlugin("paddlejs-plugin");
plugin.register(paddlejs, wx);

export const PaddleJS = new paddlejs.Runner({
  modelPath: 'http://127.0.0.1', //你本地的ip地址也可以用
  feedShape: {
      fw: 224,
      fh: 224
  },
  fill: '#fff',
  targetSize: {
      height: 224,
      width: 224
  },
  bgr: false,
  mean: [0.485, 0.456, 0.406],
  std:  [0.229, 0.224, 0.225],
  needPreheat: true,
  webglFeedProcess: true
});

10)现在拿出你转换后的模型,进入目录,使用python -m http.server 80进行挂载,这样可以通过127.0.0.1进行访问 这也是为什么modelPath填写127.0.0.1的原因,你可以测试一下,现在是否能通过127.0.0.1/model.json访问model.json
11)如果初始化成功,那么就剩下预测的代码了。

test: function(){
    wx.chooseImage({
      count: 1,
      sizeType: ['original'],
      sourceType: ['album', 'camera'],
      success:res => {
        console.log(res)
        this.setData({
          imageSrc: res.tempFilePaths[0]      
        })

        wx.getImageInfo({
          src: res.tempFilePaths[0],
          success: res=> {

            let {width, height, path} = res;
            
            const ctx = wx.createCanvasContext("myCanvas")
            console.log(ctx)
            ctx.drawImage(path, 0, 0, width, height);
            ctx.draw(false, () => {

              wx.canvasGetImageData({
                canvasId: "myCanvas",
                height: height,
                width: width,
                x: 0,
                y: 0,
                success: res => {

                  PaddleJS.predict(res).then(res =>{
                    console.log(res)
                    const max = Math.max.apply(null, res);
                    const index = res.indexOf(max);
                    console.log(index, max)
                    console.log(labelMap[index])
                    
                  })
                },
                fail: res => {
                  console.log(res)
                }
              },)
            })
          }
        })
      }
    }) 
  },

12)最后编译,可以在模拟器中查看和调用。
在这里插入图片描述
如果要更换模型,需要先清理缓存(全部清理),然后重新编译。

现在存在两个问题:
1、很多paddlepaddle模型转换会报错(错误就没有具体深究)
2、速度比较慢(facedetect的demo测试约4-5秒,垃圾分类模型约180ms)。

MNN.js

MNN.js

NCNN

tfjs

openvinojs

onnxruntimejs

wasm+wasi替代docker,服务端

webgl

部分功能实现

SQL

SQL

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

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

相关文章

平台总线式驱动开发——基本框架

1. 总线、设备和驱动 硬编码式的驱动开发带来的问题: 垃圾代码太多结构不清晰一些统一设备功能难以支持开发效率低下 1.1 初期解决思路:设备与驱动分离 struct device来表示一个具体设备,主要提供具体设备相关的资源(如寄存器地…

ES为什么要移除types类型

文章目录elasticsearch(集群)中可以包含多个索引index(数据库) ,每个索引中可以包含多个类型types(表) ,每个类型下又包含多个文档Document(行) ,每个文档中又包含多个字段Field&…

姿态估计评价指标

PCK 正确估计出关键点的百分比 (Percentage of Correct Keypoints),现在已基本不用。 PCKik∑iδ(did≤Tk)∑i1PCK_i^k\frac{\sum_i\delta(\frac{d_i}{d}\leq T_k)}{\sum_i1} PCKik​∑i​1∑i​δ(ddi​​≤Tk​)​ 检测出的关键点与其对应…

1 机器学习之线性回归

学习笔记自,慕课网 《Python3 入门人工智能》 https://coding.imooc.com/lesson/418.html#mid33109 麻雀虽小,五脏俱全 1.1 回归分析 1.2 线性回归问题求解 1.3 寻找最合适的 a、b,引入损失函数的概念 尽可能使损失函数最小即找到了最合适的…

(重要)实数域上一切范数等价的证明

证明:实数域上一切范数等价编辑切换为居中添加图片注释,不超过 140 字(可选)首先需要明确范数等价的条件,这里的条件等价于夹逼,就是A小于等于B,B小于等于A,那么A肯定等于B。利用这个…

【MySQL】InnoDB存储引擎的行结构

文章目录前言1、MySQL的体系结构2、InnoDB逻辑存储结构3、InnoDB记录行结构3.1、概述3.2、语法操作3.3、Compact行格式3.3.1、示意图3.3.2、记录的额外信息3.3.3、记录的真实数据3.3.4、定长字段补充3.4、行溢出前言 MySQL服务器上负责对表中数据的读取和写入工作的部分是存储…

【博学谷学习记录超强总结,用心分享|产品经理基础总结和感悟14】

TOC 第三章, 内容服务平台优化思考 前文中,我们粗略分析了用户阅读内容的诉求和创作者编制内容的诉求,本章笔者尝试结合用户诉求分析平台的内容分发策略,结合创作者诉求分析创作者后台设计思路,创作者后台分析主要从…

Java实现支付宝支付,内网穿透,支付功能实现-57

一:支付业务 1.1 支付宝业务简介 1)网页跳转到支付宝收银台页面。用户可以使用支付宝App扫一扫屏幕二维码,待手机提示付款后选择支付工具输入密码即可完成支付; 2)如果不使用手机支付,也可以点击上图右侧…

Visual Studio解决方案中添加src文件夹的方法

如标题,这个听起来是一个愚蠢的问题,但如果在Visual Studio想添加一个src文件夹,而命名空间不包含src的话,似乎还真不容易。 如果在Visual Studio里新建一个空白解决方案,然后右键解决方案->添加->新建解决方案…

鲲鹏BigData Pro解决方案中Hive组件的部署

1 介绍 本博文基于《鲲鹏Bigdata pro之Hive集群部署》的实验手册进行,目的是方便Hive学习者重用(从本文复制)相关的指令、配置和代码。同时,会对相关的Bash命令解释,达到增进理解的目的。 2 Hive组件的部署 部署的前…

探索SpringMVC-HandlerAdapter之RequestMappingHandlerAdapter-参数解析

前言 上回,我们大概讲了下HandlerAdapter。今天带大家来认识一下,我们最常用的RequestMappingHandlerAdapter。不过只能给大家先开个头,讲下参数解析。 RequestMappingHandlerAdapter 在介绍HandlerAdapter时,我们就知道Handle…

自己动手写编译器:从NFA到DFA

上一节我们完成了使用NFA来识别字符串的功能。NFA有个问题就是其状态节点太多,使用起来效率不够好。本节我们介绍一种叫“子集构造”的算法,将拥有多个节点的NFA转化为DFA。在上一节我们描述的epsilon闭包操作可以看到,实际上所有由epsilon边…

「ARM32」MMU和页表的映射过程详解

在ARM32中,MMU主要完成虚拟地址到物理地址的映射,并且能够控制内存的访问权限,而页表是实现上述功能的主要手段。页表又分为一级页表、二级页表,在ARM64中甚至还有三级页表。为了便于理解,本章主要讲述一级页表完成段映…

centos7 安装Mysql详细教程

centos7 弃用了Mysql,默认安装了MariaDB,MariaDB是Mysql一个分支,所以要想在centos上安装Mysql,需要先进行卸载MariaDB,避免冲突 本次教程所用环境: 腾讯云服务器:centos7Mysql5.7 1. 卸载Ma…

dubbo源码实践-protocol层-invoker理解

1概述Invoker官方解释:Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个…

Python 机器学习最常打交道的 27 款工具包

为了大家能够对人工智能常用的 Python 库有一个初步的了解,以选择能够满足自己需求的库进行学习,对目前较为常见的人工智能库进行简要全面的介绍。 1、Numpy NumPy(Numerical Python)是 Python的一个扩展程序库,支持大量的维度数组与矩阵运算…

Maix Bit(K210)保姆级入门上手教程

Maix Bit(K210)快速上手 这是K210快速上手系列文章,主要内容是,设备连接,环境准备,运行第一个程序 阅读文章前提:python基础,K210是使用Micropython脚本语法的,因此需要一些python…

RocketMQ5.0.0部署与实例

一、Idea调试1.相关配置文件在E:\rocketmq创建conf、logs、store三个文件夹。从RocketMQ distribution部署目录中将broker.conf、logback_namesrv.xml、logback_broker.xml文件复制到conf目录。如下图所示。其中logback_namesrv.xml、logback_broker.xml分别是NameServer、Brok…

纯C语言实现动态爱心(详解,初学者也能看懂)

文章目录✍动态爱心实现💖一段小故事:爱心函数的由来🎈 创建动态爱心的准备(非小白可以跳过)1.爱心字符2.对easyx库里面的基础函数的认识①initgraph函数②settextcolor、settextstyle、setbkmode、outtextxy四种函数③…

PostgresSQL数据库的使用

PostgresSQL数据库的使用 下载安装 数据类型 使用指导 数据库操作 连接控制台 psql -h <实例连接地址> -U <用户名> -p <端口号>参数描述实例连接地址RDS PostgreSQL实例的连接地址&#xff0c;本机可用localhost或者127.0.0.1用户名创建的RDS Postgre…