关于rust:用-WasmEdge-和-YoMo-对实时数据流进行-AI-推理

YoMo 是一个用于辅助开发者不便构建分布式云零碎(Geo-Distributed Cloud System)的编程框架。YoMo 的通信层构建在 QUIC 协定之上,带来高速数据传输的同时,内置了 Streaming Serverless 的“流函数”,大幅晋升了分布式云零碎的开发体验。YoMo 构建的分布式云零碎在近场算力和终端之间提供了超高速通信机制,在 Metaverse、VR/AR、IoT 等畛域有宽泛的利用场景。

YoMo 应用 Go 语言编写,Streaming Serverless 局部应用了 Golang 的插件和共享库动静加载用户代码和共享库,但也给开发者带来了一些局限性,尤其是应用 Windows 的开发者。加之Serverless 架构对隔离的刚性需要,这使得 WebAssembly 成为运行用户定义函数的绝佳抉择。

例如在 AR/VR、智能工厂里做实时 AI 推理的过程中,摄像头能够通过 YoMo 将实时的非结构化数据发送到近场 MEC (多拜访边缘计算)设施中的计算节点,并主动执行托管的 AI 推理函数。当 AI 推理实现,YoMo将 AI 计算结果实时发送给端设施。

然而,YoMo 面临的挑战是在边缘计算节点中合并和治理由多个内部开发者编写的处理程序函数。这须要在不就义性能的状况下对这些函数进行 runtime 隔离。传统的软件容器解决方案,如 Docker,无奈胜任这项工作,因为太重且速度太慢,无奈解决实时工作。

WebAssembly 提供了一个轻量级高性能的软件容器。它非常适合作为 YoMo 数据处理 handler 函数的 runtime。

本文中,咱们将向你展现如何为基于 Tensorflow 的图片辨认创立 Rust 函数,将其编译为 WebAssembly,而后应用 YoMo 将其作为流数据 handler 运行。咱们应用 WasmEdge 作为 WebAssembly runtime,因为与其它 WebAssembly runtime 相比,WasmEdge 提供了最佳性能和最高灵便度。WasmEdge 是惟一稳固反对 Tensorflow 的 WebAssembly 虚拟机。 YoMo 通过 WasmEdge 的 Golang API治理 WasmEdge VM 实例和容器内的 WebAssembly 字节码利用。

GitHub 源代码:https://github.com/yomorun/yo…

筹备工作

显然,须要装置 Golang 。咱们假如你曾经装置。

Golang 版本须要比 1.15 新,咱们的示例能力运行。

同时,须要装置 YoMo CLI 应用程序。它安顿和协调数据流和 handler 函数调用。

$ go install github.com/yomorun/cli/yomo@latest
$ yomo version
YoMo CLI version: v0.0.5

接下来,请装置 WasmEdge 及 Tensorflow 共享库。 WasmEdge 是当先的 WebAssembly runtime,由 CNCF 托管。 咱们将应用它嵌入和运行来自 YoMo 的 WebAssembly 程序。

# Install WasmEdge
$ wget https://github.com/second-state/WasmEdge-go/releases/download/v0.8.1/install_wasmedge.sh
$ chmod +x ./install_wasmedge.sh
$ sudo ./install_wasmedge.sh /usr/local

# Install WasmEdge Tensorflow extension
$ wget https://github.com/second-state/WasmEdge-go/releases/download/v0.8.1/install_wasmedge_tensorflow_deps.sh
$ wget https://github.com/second-state/WasmEdge-go/releases/download/v0.8.1/install_wasmedge_tensorflow.sh
$ chmod +x ./install_wasmedge_tensorflow_deps.sh
$ chmod +x ./install_wasmedge_tensorflow.sh
$ sudo ./install_wasmedge_tensorflow_deps.sh /usr/local
$ sudo ./install_wasmedge_tensorflow.sh /usr/local

# Install WasmEdge Images extension
$ wget https://github.com/second-state/WasmEdge-go/releases/download/v0.8.1/install_wasmedge_image_deps.sh
$ wget https://github.com/second-state/WasmEdge-go/releases/download/v0.8.1/install_wasmedge_image.sh
$ chmod +x ./install_wasmedge_image_deps.sh
$ chmod +x ./install_wasmedge_image.sh
$ sudo ./install_wasmedge_image_deps.sh /usr/local
$ sudo ./install_wasmedge_image.sh /usr/local

最初, 因为咱们的 demo WebAssembly 函数是用 Rust 编写的,因而你还须要装置 Rust 编译器和 rustwasmc工具链。

demo 的其它局部能够 fork 和 clone 源代码 repo。

$ git clone https://github.com/yomorun/yomo-wasmedge-tensorflow.git

图片分类函数

解决 YoMo 图片流的图片辨认函数是用 Rust 编写的。 它用 WasmEdge Tensorflow API 来解决输出图片。

#[wasm_bindgen]
pub fn infer(image_data: &[u8]) -> String {
    // Load the TFLite model and its meta data (the text label for each recognized object number)
    let model_data: &[u8] = include_bytes!("lite-model_aiy_vision_classifier_food_V1_1.tflite");
    let labels = include_str!("aiy_food_V1_labelmap.txt");

    // Pre-process the image to a format that can be used by this model
    let flat_img = wasmedge_tensorflow_interface::load_jpg_image_to_rgb8(image_data, 192, 192);
    
    // Run the TFLite model using the WasmEdge Tensorflow API
    let mut session = wasmedge_tensorflow_interface::Session::new(&model_data, wasmedge_tensorflow_interface::ModelType::TensorFlowLite);
    session.add_input("input", &flat_img, &[1, 192, 192, 3])
           .run();
    let res_vec: Vec<u8> = session.get_output("MobilenetV1/Predictions/Softmax");

    // Find the object index in res_vec that has the greatest probability
    // Translate the probability into a confidence level
    // Translate the object index into a label from the model meta data food_name
    
    ret_str = format!(
        "It {} a <a href='https://www.google.com/search?q={}'>{}</a> in the picture",
        confidence, food_name, food_name
    );
    return ret_str;
}

你能够应用 rustwasmc 工具将该函数编译为 WebAssembly 字节码。

这里,咱们要求 Rust 编译器版本为 1.50 或更早,能力让 WebAssembly 函数与 WasmEdge 的 Golang API 一起应用。一旦 interface type 标准最终确定并失去反对,咱们会赶上最新的Rust 编译器版本 。

$ rustup default 1.50.0

$ cd flow/rust_mobilenet_food
$ rustwasmc  build `--enable-ext`
# The output WASM will be pkg/rust_mobilenet_food_lib_bg.wasm.

# Copy the wasm bytecode file to the flow/ directory
$ cp pkg/rust_mobilenet_food_lib_bg.wasm ../

与 YoMo 集成

在 YoMo 这端,咱们应用 WasmEdge Golang API 来为图片辨认函数启动和运行 WasmEdge 虚拟机。 app.go 文件在源代码我的项目中如下:

package main

... ...

var (
    vm      *wasmedge.VM
    vmConf  *wasmedge.Configure
    counter uint64
)

func main() {
    // Initialize WasmEdge's VM
    initVM()
    defer vm.Delete()
    defer vmConf.Delete()

    // Connect to Zipper service
    cli, err := client.NewServerless("image-recognition").Connect("localhost", 9000)
    if err != nil {
        log.Print("❌ Connect to zipper failure: ", err)
        return
    }

    defer cli.Close()
    cli.Pipe(Handler)
}

// Handler process the data in the stream
func Handler(rxStream rx.RxStream) rx.RxStream {
    stream := rxStream.
        Subscribe(ImageDataKey).
        OnObserve(decode).
        Encode(0x11)
        
    return stream
}

// decode Decode and perform image recognition
var decode = func(v []byte) (interface{}, error) {
    // get image binary
    p, _, _, err := y3.DecodePrimitivePacket(v)
    if err != nil {
        return nil, err
    }
    img := p.ToBytes()

    // recognize the image
    res, err := vm.ExecuteBindgen("infer", wasmedge.Bindgen_return_array, img)
    
    return hash, nil
}

... ...

// initVM initialize WasmEdge's VM
func initVM() {
    wasmedge.SetLogErrorLevel()
    vmConf = wasmedge.NewConfigure(wasmedge.WASI)
    vm = wasmedge.NewVMWithConfig(vmConf)

    var wasi = vm.GetImportObject(wasmedge.WASI)
    wasi.InitWasi(
        os.Args[1:],     /// The args
        os.Environ(),    /// The envs
        []string{".:."}, /// The mapping directories
        []string{},      /// The preopens will be empty
    )

    /// Register WasmEdge-tensorflow and WasmEdge-image
    var tfobj = wasmedge.NewTensorflowImportObject()
    var tfliteobj = wasmedge.NewTensorflowLiteImportObject()
    vm.RegisterImport(tfobj)
    vm.RegisterImport(tfliteobj)
    var imgobj = wasmedge.NewImageImportObject()
    vm.RegisterImport(imgobj)

    /// Instantiate wasm
    vm.LoadWasmFile("rust_mobilenet_food_lib_bg.wasm")
    vm.Validate()
    vm.Instantiate()
}

运行

最初,咱们启动 YoMo 并查看整个数据处理管道的运行状况。从我的项目文件夹启动 YoMo CLI 应用程序。 yaml文件定义了 YoMo 应听取的端口以及触发传入数据的工作流 handler。请留神,流名称 image-recognition 与下面提到的数据 handler app.go 相匹配。

$ yomo serve -c ./zipper/workflow.yaml

通过运行下面提到的 app.go 程序启动 handler 程序。

$ cd flow
$ go run --tags "tensorflow image" app.go

通过给 YoMo 发送数据来启动模仿数据源。 视频是一系列图片帧。 app.go 中的 WasmEdge 函数将针对视频中的每个图片帧进行调用。

# Download a video file
$ wget -P source 'https://github.com/yomorun/yomo-wasmedge-tensorflow/releases/download/v0.1.0/hot-dog.mp4'

# Stream the video to YoMo
$ go run ./source/main.go ./source/hot-dog.mp4

你能够在控制台中看到 WasmEdge handler函数的输入。它将在视频的每个图片帧中检测到的对象的名称进行打印。

展望未来

本文探讨了如何应用 YoMo 框架中的 WasmEdge Tensorflow API 和 Golang SDK 来几近实时地解决图片流。

与 YoMo 单干,咱们很快将在智能工厂的理论生产中部署 WasmEdge,用于各种装配线上的工作。 WasmEdge 是边缘计算的软件 runtime!

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据