From 3a087c4244aec1a50d06949d3b4f4211dc71f82e Mon Sep 17 00:00:00 2001 From: YAMAMOTO Takashi Date: Thu, 12 Jun 2025 10:33:25 +0900 Subject: [PATCH] wamr-wasi-extensions: add a cmake package to provide our wasi extension (#4344) * wasi_ephemeral_nn.h: add a convenience wrapper header * wamr-wasi-extensions: add a cmake package to provide our wasi extension the sample app was tested with: * wasmtime * iwasm with https://github.com/bytecodealliance/wasm-micro-runtime/pull/4308 currently only contains wasi-nn. maybe it makes sense to add lib-socket things as well. cf. https://github.com/bytecodealliance/wasm-micro-runtime/issues/4288 --- .../wasi-nn/include/wasi_ephemeral_nn.h | 7 + wamr-wasi-extensions/CMakeLists.txt | 8 + wamr-wasi-extensions/nn/CMakeLists.txt | 25 +++ .../samples/nn/CMakeLists.txt | 13 ++ wamr-wasi-extensions/samples/nn/app.c | 169 ++++++++++++++++++ wamr-wasi-extensions/test.sh | 19 ++ 6 files changed, 241 insertions(+) create mode 100644 core/iwasm/libraries/wasi-nn/include/wasi_ephemeral_nn.h create mode 100644 wamr-wasi-extensions/CMakeLists.txt create mode 100644 wamr-wasi-extensions/nn/CMakeLists.txt create mode 100644 wamr-wasi-extensions/samples/nn/CMakeLists.txt create mode 100644 wamr-wasi-extensions/samples/nn/app.c create mode 100755 wamr-wasi-extensions/test.sh diff --git a/core/iwasm/libraries/wasi-nn/include/wasi_ephemeral_nn.h b/core/iwasm/libraries/wasi-nn/include/wasi_ephemeral_nn.h new file mode 100644 index 000000000..6a4901afc --- /dev/null +++ b/core/iwasm/libraries/wasi-nn/include/wasi_ephemeral_nn.h @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2025 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#define WASM_ENABLE_WASI_EPHEMERAL_NN 1 +#include "wasi_nn.h" diff --git a/wamr-wasi-extensions/CMakeLists.txt b/wamr-wasi-extensions/CMakeLists.txt new file mode 100644 index 000000000..e5fabb674 --- /dev/null +++ b/wamr-wasi-extensions/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (C) 2025 Midokura Japan KK. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 3.14) + +project(wamr-wasi-extensions LANGUAGES C) + +add_subdirectory(nn) diff --git a/wamr-wasi-extensions/nn/CMakeLists.txt b/wamr-wasi-extensions/nn/CMakeLists.txt new file mode 100644 index 000000000..27c22c4b8 --- /dev/null +++ b/wamr-wasi-extensions/nn/CMakeLists.txt @@ -0,0 +1,25 @@ +# Copyright (C) 2025 Midokura Japan KK. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +add_library(wamr-wasi-nn INTERFACE) + +set(wasi_nn_header_dir ${CMAKE_CURRENT_SOURCE_DIR}/../../core/iwasm/libraries/wasi-nn/include) + +set(headers + ${wasi_nn_header_dir}/wasi_ephemeral_nn.h + ${wasi_nn_header_dir}/wasi_nn.h + ${wasi_nn_header_dir}/wasi_nn_types.h +) + +set_property(TARGET wamr-wasi-nn PROPERTY PUBLIC_HEADER ${headers}) + +target_include_directories(wamr-wasi-nn + INTERFACE + $ + $) + +install(TARGETS wamr-wasi-nn + EXPORT wamr-wasi-nn-config + PUBLIC_HEADER DESTINATION include/wamr) +install(EXPORT wamr-wasi-nn-config + DESTINATION lib/cmake/wamr-wasi-nn) diff --git a/wamr-wasi-extensions/samples/nn/CMakeLists.txt b/wamr-wasi-extensions/samples/nn/CMakeLists.txt new file mode 100644 index 000000000..59d607f64 --- /dev/null +++ b/wamr-wasi-extensions/samples/nn/CMakeLists.txt @@ -0,0 +1,13 @@ +# Copyright (C) 2025 Midokura Japan KK. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required(VERSION 3.14) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED YES) +set(CMAKE_C_EXTENSIONS NO) + +project(nn-classification-openvino LANGUAGES C) +add_executable(nn-classification-openvino "app.c") +find_package(wamr-wasi-nn REQUIRED) +target_link_libraries(nn-classification-openvino wamr-wasi-nn) diff --git a/wamr-wasi-extensions/samples/nn/app.c b/wamr-wasi-extensions/samples/nn/app.c new file mode 100644 index 000000000..045d1bd4b --- /dev/null +++ b/wamr-wasi-extensions/samples/nn/app.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2025 Midokura Japan KK. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * what this application does is basically same as: + * https://github.com/bytecodealliance/wasmtime/tree/efa236e58d09570baaf27865da33fb852fcf40a5/crates/wasi-nn/examples/classification-example + * + * map_file/unmap_file are copy-and-pasted from: + * https://github.com/yamt/toywasm/blob/0eaad8cacd0cc7692946ff19b25994f106113be8/lib/fileio.c + */ + +int +map_file(const char *path, void **pp, size_t *sizep) +{ + void *p; + size_t size; + ssize_t ssz; + int fd; + int ret; + + fd = open(path, O_RDONLY); + if (fd == -1) { + ret = errno; + assert(ret != 0); + return ret; + } + struct stat st; + ret = fstat(fd, &st); + if (ret == -1) { + ret = errno; + assert(ret != 0); + close(fd); + return ret; + } + size = st.st_size; + if (size > 0) { + p = malloc(size); + } + else { + /* Avoid a confusing error */ + p = malloc(1); + } + if (p == NULL) { + close(fd); + return ENOMEM; + } + ssz = read(fd, p, size); + if (ssz != size) { + ret = errno; + assert(ret != 0); + close(fd); + return ret; + } + close(fd); + *pp = p; + *sizep = size; + return 0; +} + +void +unmap_file(void *p, size_t sz) +{ + free(p); +} + +static void +print_result(const float *result, size_t sz) +{ + /* + * just dump the raw result. + * you can postprocess the output with eg. "sort -k2nr | head" + */ + int i; + for (i = 0; i < sz / sizeof(float); i++) { + printf("%d %f\n", i, result[i]); + } +} + +int +main(int argc, char **argv) +{ + wasi_nn_error nnret; + int ret; + void *xml; + size_t xmlsz; + ret = map_file("fixture/model.xml", &xml, &xmlsz); + if (ret != 0) { + fprintf(stderr, "failed to load fixture/model.xml: %s\n", + strerror(ret)); + exit(1); + } + void *weights; + size_t weightssz; + ret = map_file("fixture/model.bin", &weights, &weightssz); + if (ret != 0) { + fprintf(stderr, "failed to load fixture/model.bin: %s\n", + strerror(ret)); + exit(1); + } + /* note: openvino takes two buffers, namely IR and weights */ + graph_builder builders[2] = { { + .buf = xml, + .size = xmlsz, + }, + { + .buf = weights, + .size = weightssz, + } }; + graph g; + nnret = load(builders, 2, openvino, cpu, &g); + unmap_file(xml, xmlsz); + unmap_file(weights, weightssz); + if (nnret != success) { + fprintf(stderr, "load failed with %d\n", (int)nnret); + exit(1); + } + graph_execution_context ctx; + nnret = init_execution_context(g, &ctx); + if (nnret != success) { + fprintf(stderr, "init_execution_context failed with %d\n", (int)nnret); + exit(1); + } + void *tensordata; + size_t tensordatasz; + ret = map_file("fixture/tensor.bgr", &tensordata, &tensordatasz); + if (ret != 0) { + fprintf(stderr, "failed to load fixture/tensor.bgr: %s\n", + strerror(ret)); + exit(1); + } + tensor tensor = { + .dimensions = { .buf = (uint32_t[]){1, 3, 224, 224,}, .size = 4, }, + .type = fp32, + .data = tensordata, + }; + nnret = set_input(ctx, 0, &tensor); + unmap_file(tensordata, tensordatasz); + if (nnret != success) { + fprintf(stderr, "set_input failed with %d\n", (int)nnret); + exit(1); + } + nnret = compute(ctx); + if (nnret != success) { + fprintf(stderr, "compute failed with %d\n", (int)nnret); + exit(1); + } + float result[1001]; + uint32_t resultsz; + nnret = get_output(ctx, 0, (void *)result, sizeof(result), &resultsz); + if (nnret != success) { + fprintf(stderr, "get_output failed with %d\n", (int)nnret); + exit(1); + } + print_result(result, resultsz); +} diff --git a/wamr-wasi-extensions/test.sh b/wamr-wasi-extensions/test.sh new file mode 100755 index 000000000..585a444bd --- /dev/null +++ b/wamr-wasi-extensions/test.sh @@ -0,0 +1,19 @@ +#! /bin/sh + +# Copyright (C) 2025 Midokura Japan KK. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +PREFIX=/tmp/wamr +WASI_SDK=${WASI_SDK:-/opt/wasi-sdk} + +cmake -B build-lib \ +-DCMAKE_TOOLCHAIN_FILE=${WASI_SDK}/share/cmake/wasi-sdk.cmake \ +-DCMAKE_INSTALL_PREFIX=${PREFIX} \ +. +cmake --build build-lib -t install + +cmake -B build-app-nn \ +-DCMAKE_TOOLCHAIN_FILE=${WASI_SDK}/share/cmake/wasi-sdk.cmake \ +-DCMAKE_PREFIX_PATH=${PREFIX} \ +samples/nn +cmake --build build-app-nn