复杂推理模型从服务器移植到Web浏览器的理论和实战

本文介绍了如何使用Pyodide将复杂Python推理模型移植到Web浏览器中,通过在浏览器中运行原生Python代码,实现前后处理和矩阵运算。Pyodide基于WebAssembly,允许JavaScript与Python的互访,通过代理对象进行内存访问。文章详细讲解了原理、实践步骤和存在的问题,提供了一个高效移植模型的方法。
摘要由CSDN通过智能技术生成

一 背景

随着机器学习的应用面越来越广,能在浏览器中跑模型推理的Javascript框架引擎也越来越多了。在项目中,前端同学可能会找到一些跑在服务端的python算法模型,很想将其直接集成到自己的代码中,以Javascript语言在浏览器中运行。

对于一部分简单的模型,推理的前处理、后处理比较容易,不涉及复杂的科学计算,碰到这种模型,最多做个模型格式转化,然后用推理框架直接跑就可以了,这种移植成本很低。

而很大一部分模型会涉及复杂的前处理、后处理,包括大量的矩阵运算、图像处理等Python代码。这种情况一般的思路就是用Javascript语言将Python代码手工翻译一遍,这么做的问题是费时费力还容易出错。

Pyodide作为浏览器中的科学计算框架,很好的解决了这个问题:浏览器中运行原生的Python代码进行前、后处理,大量numpy、scipy的矩阵、张量等计算无需翻译为Javascript,为移植节省了很多工作。本文就基于pyodide框架,从理论和实战两个角度,帮助前端同学解决复杂模型的移植这一棘手问题。

二 原理篇

Pyodide是个可以在浏览器中跑的WebAssembly(wasm)应用。它基于CPython的源代码进行了扩展,使用emscripten编译成为wasm,同时也把一大堆科学计算相关的pypi包也编译成了wasm,这样就能在浏览器中解释执行python语句进行科学计算了。所以pyodide也必然遵循wasm的各种约束。Pyodide在浏览器中的位置如下图所示:

1 wasm内存布局

这是wasm线性内存的布局:

Data数据段是从0x400开始的, Function Table表也在其中,起始地址为memoryBase(Emscripten中默认为1024,即0x400),STACKTOP为栈地址起始,堆地址起始为STACK_MAX。而我们实际更关心的是Javascript内存与wasm内存的互相访问。

2 Javascript与Python的互访

浏览器基于安全方面的考虑,防止wasm程序把浏览器搞崩溃,通过把wasm运行在一个沙箱化的执行环境中,禁止了wasm程序访问Javascript内存,而Javascript代码却可以访问wasm内存。因为wasm内存本质上是一个巨大的ArrayBuffer,接受Javascript的管理。我们称之为“单向内存访问”。

作为一个wasm格式的普通程序,pyodide被调用起来后,当然只能直接访问wasm内存。

为了实现互访,pyodide引入了proxy,类似于指针:在Javascript侧,通过一个PyProxy对象来引用python内存里的对象;在Python侧,通过一个JsProxy对象来引用Javascript内存里的对象。

在Javascript侧生成一个PyProxy对象:

const arr_pyproxy = pyodide.globals.get('arr')  // arr是python里的一个全局对象

在Python侧生成一个JsProxy对象:

import js
from js import foo   # foo是Javascript里的一个全局对象

互访时的类型转换分为如下三个等级:

  • 【自动转换】对于简单类型,如数字、字符串、布尔等,会被自动拷贝内存值,此时产生的就不是Proxy、而是最终的值了。
  • 【半自动转换】非简单的内置类型,都需要通过to_js()、to_py()方式来显式转换:对于Python内置的list、dict、numpy.ndarray等对象,不属于简单类型,不会自动转换类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值