Skip to content

Commit a61f068

Browse files
authored
Add an initial wasi-nn implementation for Wasmtime (#2208)
* Add an initial wasi-nn implementation for Wasmtime This change adds a crate, `wasmtime-wasi-nn`, that uses `wiggle` to expose the current state of the wasi-nn API and `openvino` to implement the exposed functions. It includes an end-to-end test demonstrating how to do classification using wasi-nn: - `crates/wasi-nn/tests/classification-example` contains Rust code that is compiled to the `wasm32-wasi` target and run with a Wasmtime embedding that exposes the wasi-nn calls - the example uses Rust bindings for wasi-nn contained in `crates/wasi-nn/tests/wasi-nn-rust-bindings`; this crate contains code generated by `witx-bindgen` and eventually should be its own standalone crate * Test wasi-nn as a CI step This change adds: - a GitHub action for installing OpenVINO - a script, `ci/run-wasi-nn-example.sh`, to run the classification example
1 parent 61a0bcb commit a61f068

33 files changed

Lines changed: 1554 additions & 1 deletion

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# install-openvino
2+
3+
A GitHub action to install OpenVINO from a package repository. This is only necessary for `wasi-nn` support but there
4+
are enough steps here to package the functionality separately and avoid cluttering the CI.
5+
6+
Future improvements:
7+
- make this installer work for different OS/distributions (e.g. https://docs.openvinotoolkit.org/latest/openvino_docs_install_guides_installing_openvino_windows.html)
8+
- it would be nice to output the install directory (i.e. `/opt/intel/openvino`)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
name: 'Install OpenVINO'
2+
description: 'Install OpenVINO binaries from a package repository; this is significantly faster than building from source'
3+
4+
inputs:
5+
version:
6+
description: 'The release version of OpenVINO to install'
7+
required: false
8+
default: '2020.4.287'
9+
10+
runs:
11+
using: composite
12+
steps:
13+
- run: ${{ github.action_path }}/install.sh ${{ inputs.version }}
14+
shell: bash
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Retrieve OpenVINO checksum.
6+
wget https://apt.repos.intel.com/openvino/2020/GPG-PUB-KEY-INTEL-OPENVINO-2020
7+
echo '5f5cff8a2d26ba7de91942bd0540fa4d GPG-PUB-KEY-INTEL-OPENVINO-2020' > CHECKSUM
8+
md5sum --check CHECKSUM
9+
10+
# Add OpenVINO repository (deb).
11+
sudo apt-key add GPG-PUB-KEY-INTEL-OPENVINO-2020
12+
echo "deb https://apt.repos.intel.com/openvino/2020 all main" | sudo tee /etc/apt/sources.list.d/intel-openvino-2020.list
13+
sudo apt update
14+
15+
# Install OpenVINO package.
16+
sudo apt install -y intel-openvino-runtime-ubuntu18-$1

.github/workflows/main.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ jobs:
5151
runs-on: ubuntu-latest
5252
env:
5353
RUSTDOCFLAGS: -Dbroken_intra_doc_links
54+
OPENVINO_SKIP_LINKING: 1
5455
steps:
5556
- uses: actions/checkout@v2
5657
with:
@@ -252,6 +253,7 @@ jobs:
252253
--all \
253254
--exclude lightbeam \
254255
--exclude wasmtime-lightbeam \
256+
--exclude wasmtime-wasi-nn \
255257
--exclude peepmatic \
256258
--exclude peepmatic-automata \
257259
--exclude peepmatic-fuzzing \
@@ -304,6 +306,23 @@ jobs:
304306
CARGO_VERSION: "+nightly"
305307
RUST_BACKTRACE: 1
306308

309+
# Build and test the wasi-nn module.
310+
test_wasi_nn:
311+
name: Test wasi-nn module
312+
runs-on: ubuntu-latest
313+
steps:
314+
- uses: actions/checkout@v2
315+
with:
316+
submodules: true
317+
- uses: ./.github/actions/install-rust
318+
with:
319+
toolchain: nightly-2020-08-25
320+
- run: rustup target add wasm32-wasi
321+
- uses: ./.github/actions/install-openvino
322+
- run: ./ci/run-wasi-nn-example.sh
323+
env:
324+
RUST_BACKTRACE: 1
325+
307326
# Verify that cranelift's code generation is deterministic
308327
meta_determinist_check:
309328
name: Meta deterministic check
@@ -411,6 +430,7 @@ jobs:
411430
--all \
412431
--exclude lightbeam \
413432
--exclude wasmtime-lightbeam \
433+
--exclude wasmtime-wasi-nn \
414434
--exclude peepmatic \
415435
--exclude peepmatic-automata \
416436
--exclude peepmatic-fuzzing \

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,6 @@
77
[submodule "WASI"]
88
path = crates/wasi-common/WASI
99
url = https://github.com/WebAssembly/WASI
10+
[submodule "crates/wasi-nn/spec"]
11+
path = crates/wasi-nn/spec
12+
url = https://github.com/WebAssembly/wasi-nn

Cargo.lock

Lines changed: 127 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ wasmtime-jit = { path = "crates/jit", version = "0.21.0" }
3030
wasmtime-obj = { path = "crates/obj", version = "0.21.0" }
3131
wasmtime-wast = { path = "crates/wast", version = "0.21.0" }
3232
wasmtime-wasi = { path = "crates/wasi", version = "0.21.0" }
33+
wasmtime-wasi-nn = { path = "crates/wasi-nn", version = "0.21.0", optional = true }
3334
wasi-common = { path = "crates/wasi-common", version = "0.21.0" }
3435
structopt = { version = "0.3.5", features = ["color", "suggestions"] }
3536
object = { version = "0.22.0", default-features = false, features = ["write"] }
@@ -80,6 +81,7 @@ default = ["jitdump", "wasmtime/wat", "wasmtime/parallel-compilation"]
8081
lightbeam = ["wasmtime/lightbeam"]
8182
jitdump = ["wasmtime/jitdump"]
8283
vtune = ["wasmtime/vtune"]
84+
wasi-nn = ["wasmtime-wasi-nn"]
8385

8486
# Try the experimental, work-in-progress new x86_64 backend. This is not stable
8587
# as of June 2020.

ci/run-experimental-x64-ci.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ cargo $CARGO_VERSION \
1313
--features experimental_x64 \
1414
--all \
1515
--exclude wasmtime-lightbeam \
16+
--exclude wasmtime-wasi-nn \
1617
--exclude peepmatic \
1718
--exclude peepmatic-automata \
1819
--exclude peepmatic-fuzzing \

ci/run-wasi-nn-example.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
3+
# The following script demonstrates how to execute a machine learning inference using the wasi-nn module optionally
4+
# compiled into Wasmtime. Calling it will download the necessary model and tensor files stored separately in $FIXTURE
5+
# into $TMP_DIR (optionally pass a directory with existing files as the first argument to re-try the script). Then,
6+
# it will compile the example code in crates/wasi-nn/tests/example into a Wasm file that is subsequently
7+
# executed with the Wasmtime CLI.
8+
set -e
9+
WASMTIME_DIR=$(dirname "$0" | xargs dirname)
10+
FIXTURE=https://gist.github.com/abrown/c7847bf3701f9efbb2070da1878542c1/raw/07a9f163994b0ff8f0d7c5a5c9645ec3d8b24024
11+
12+
# Inform the environment of OpenVINO library locations. Then we use OPENVINO_INSTALL_DIR below to avoid building all of
13+
# OpenVINO from source (quite slow).
14+
source /opt/intel/openvino/bin/setupvars.sh
15+
16+
# Build Wasmtime with wasi-nn enabled; we attempt this first to avoid extra work if the build fails.
17+
OPENVINO_INSTALL_DIR=/opt/intel/openvino cargo build -p wasmtime-cli --features wasi-nn
18+
19+
# Download all necessary test fixtures to the temporary directory.
20+
TMP_DIR=${1:-$(mktemp -d -t ci-XXXXXXXXXX)}
21+
wget --no-clobber --directory-prefix=$TMP_DIR $FIXTURE/frozen_inference_graph.bin
22+
wget --no-clobber --directory-prefix=$TMP_DIR $FIXTURE/frozen_inference_graph.xml
23+
wget --no-clobber --directory-prefix=$TMP_DIR $FIXTURE/tensor-1x3x300x300-f32.bgr
24+
25+
# Now build an example that uses the wasi-nn API.
26+
pushd $WASMTIME_DIR/crates/wasi-nn/examples/classification-example
27+
cargo build --release --target=wasm32-wasi
28+
cp target/wasm32-wasi/release/wasi-nn-example.wasm $TMP_DIR
29+
popd
30+
31+
# Run the example in Wasmtime (note that the example uses `fixture` as the expected location of the model/tensor files).
32+
OPENVINO_INSTALL_DIR=/opt/intel/openvino cargo run --features wasi-nn -- run --mapdir fixture::$TMP_DIR $TMP_DIR/wasi-nn-example.wasm
33+
34+
# Clean up.
35+
rm -rf $TMP_DIR

crates/wasi-nn/Cargo.toml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
[package]
2+
name = "wasmtime-wasi-nn"
3+
version = "0.21.0"
4+
authors = ["The Wasmtime Project Developers"]
5+
description = "Wasmtime implementation of the wasi-nn API"
6+
documentation = "https://docs.rs/wasmtime-wasi-nn"
7+
license = "Apache-2.0 WITH LLVM-exception"
8+
categories = ["wasm", "computer-vision"]
9+
keywords = ["webassembly", "wasm", "neural network"]
10+
repository = "https://github.com/bytecodealliance/wasmtime"
11+
readme = "README.md"
12+
edition = "2018"
13+
14+
[dependencies]
15+
# These dependencies are necessary for the witx-generation macros to work:
16+
anyhow = "1.0"
17+
log = { version = "0.4", default-features = false }
18+
wasmtime = { path = "../wasmtime", version = "0.21.0", default-features = false }
19+
wasmtime-runtime = { path = "../runtime", version = "0.21.0" }
20+
wasmtime-wiggle = { path = "../wiggle/wasmtime", version = "0.21.0" }
21+
wasmtime-wasi = { path = "../wasi", version = "0.21.0" }
22+
wiggle = { path = "../wiggle", version = "0.21.0" }
23+
24+
# These dependencies are necessary for the wasi-nn implementation:
25+
openvino = "0.1.5"
26+
thiserror = "1.0"
27+
28+
[badges]
29+
maintenance = { status = "experimental" }

0 commit comments

Comments
 (0)