-
Notifications
You must be signed in to change notification settings - Fork 786
Add "load_by_name" API at wasi-nn #4267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1df9b7c
c5414fd
ff4ed2f
2831ff2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,6 +15,44 @@ | |||||||||||||||||||||||||||||||||||||||
| #include <stdint.h> | ||||||||||||||||||||||||||||||||||||||||
| #include "wasi_nn_types.h" | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 | ||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| load(graph_builder *builder, uint32_t builder_wasm_size, | ||||||||||||||||||||||||||||||||||||||||
| graph_encoding encoding, execution_target target, graph *g) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| load_by_name(char *name, uint32_t name_len, graph *g) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| load_by_name_with_config(const char *name, uint32_t name_len, void *config, | ||||||||||||||||||||||||||||||||||||||||
| uint32_t config_len, graph *g) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * INFERENCE | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| init_execution_context(graph g, graph_execution_context *exec_ctx) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| set_input(graph_execution_context ctx, uint32_t index, tensor *tensor) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| compute(graph_execution_context ctx) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| get_output(graph_execution_context ctx, uint32_t index, | ||||||||||||||||||||||||||||||||||||||||
| tensor_data output_tensor, uint32_t output_tensor_len, | ||||||||||||||||||||||||||||||||||||||||
| uint32_t *output_tensor_size) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_ephemeral_nn"))); | ||||||||||||||||||||||||||||||||||||||||
| #else | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
| * @brief Load an opaque sequence of bytes to use for inference. | ||||||||||||||||||||||||||||||||||||||||
| * | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -30,7 +68,7 @@ load(graph_builder_array *builder, graph_encoding encoding, | |||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| wasi_nn_error | ||||||||||||||||||||||||||||||||||||||||
| load_by_name(const char *name, graph *g) | ||||||||||||||||||||||||||||||||||||||||
| load_by_name(char *name, uint32_t name_len, graph *g) | ||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this a bug fix?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wasi_nn.h is a header for WebAssembly applications written in the C language. Is there a specific reason that we need to change it?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, its a bugfix,
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we have two sets of APIs for historical reasons, we might remove one in another PR. For now, let's ensure both are functional.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @lum1n0us wasm-micro-runtime/core/iwasm/libraries/wasi-nn/src/wasi_nn.c Lines 690 to 704 in c018b8a
Even when referring to the wasi-nn specification, the signatures declared there don’t appear to match what is used for wasi_ephemeral_nn
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @HongxiaWangSSSS I suggest we use #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
wasi_nn_error
load(graph_builder_array *builder, graph_encoding encoding,
execution_target target, graph *g)
__attribute__((import_module("wasi_ephemeral_nn")));
wasi_nn_error
load_by_name(const char *name, uint32_t len, graph *g)
__attribute__((import_module("wasi_ephemeral_nn")));
wasi_nn_error
load_by_name_with_config(const char *name, uint32_t name_len, void *config, uint32_t config_len, graph *g) __attribute__((import_module("wasi_ephemeral_nn")));;
wasi_nn_error
init_execution_context(graph g, graph_execution_context *exec_ctx) __attribute__((import_module("wasi_ephemeral_nn")));;
wasi_nn_error
set_input(graph_execution_context ctx, uint32_t index, tensor *tensor) __attribute__((import_module("wasi_ephemeral_nn")));;
wasi_nn_error
compute(graph_execution_context ctx) __attribute__((import_module("wasi_ephemeral_nn")));;
wasi_nn_error
get_output(graph_execution_context ctx, uint32_t index,
tensor_data output_tensor, uint32_t *output_tensor_size) __attribute__((import_module("wasi_ephemeral_nn")));;
#else
wasi_nn_error
load(graph_builder_array *builder, graph_encoding encoding,
execution_target target, graph *g)
__attribute__((import_module("wasi_nn")));
wasi_nn_error
init_execution_context(graph g, graph_execution_context *ctx)
__attribute__((import_module("wasi_nn")));
wasi_nn_error
set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
__attribute__((import_module("wasi_nn")));
wasi_nn_error
compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
wasi_nn_error
get_output(graph_execution_context ctx, uint32_t index,
tensor_data output_tensor, uint32_t *output_tensor_size)
__attribute__((import_module("wasi_nn")));
#endif
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a mismatch in the function signature?
and
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. YES. there should be two versions, one for wasi_ephemeral_nn, another for wasi_nn. please refer to:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If so, we need to define it at wasi_nn.h But the backend definition doesn't look like it matches (signature might be ok) wasm-micro-runtime/core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp Lines 366 to 368 in c018b8a
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. I am suggestion this #4267 (comment) as the new content of wasi_nn.h. Plus, #4267 (comment). |
||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||
|
|
@@ -86,5 +124,5 @@ wasi_nn_error | |||||||||||||||||||||||||||||||||||||||
| get_output(graph_execution_context ctx, uint32_t index, | ||||||||||||||||||||||||||||||||||||||||
| tensor_data output_tensor, uint32_t *output_tensor_size) | ||||||||||||||||||||||||||||||||||||||||
| __attribute__((import_module("wasi_nn"))); | ||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -697,6 +697,7 @@ static NativeSymbol native_symbols_wasi_nn[] = { | |
| REG_NATIVE_FUNC(get_output, "(ii*i*)i"), | ||
| #else /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */ | ||
| REG_NATIVE_FUNC(load, "(*ii*)i"), | ||
| REG_NATIVE_FUNC(load_by_name, "(*i*)i"), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. at first, i just built with -DWASM_ENABLE_WASI_NN=1.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Please do it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, does that mean that the ephemeral version is meant to be compatible with Rust (especially WasmEdge), whereas the non-ephemeral one doesn't need to be?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eventually,
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #4267 (comment)
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In my mind, wasi_ephemeral_nn is legacy and should be deprecated. If there are C APIs, they should follow the Rust API's design to avoid unnecessary changes for the runtime. |
||
| REG_NATIVE_FUNC(init_execution_context, "(i*)i"), | ||
| REG_NATIVE_FUNC(set_input, "(ii*)i"), | ||
| REG_NATIVE_FUNC(compute, "(i)i"), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,14 +85,11 @@ is_valid_graph(TFLiteContext *tfl_ctx, graph g) | |
| NN_ERR_PRINTF("Invalid graph: %d >= %d.", g, MAX_GRAPHS_PER_INST); | ||
| return runtime_error; | ||
| } | ||
| if (tfl_ctx->models[g].model_pointer == NULL) { | ||
| if (tfl_ctx->models[g].model_pointer == NULL | ||
| && tfl_ctx->models[g].model == NULL) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The original version can output different information based on various invalid argument cases. Is there a specific reason we need to merge them?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If call load_by_name(), there is no need to save the tflite buf to model_pointer.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why not free model_point after below operation in load()
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is required to validate
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whether it is
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Why is that?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. after this operation, the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. /// Builds a model based on a pre-loaded flatbuffer.
/// Caller retains ownership of the buffer and should keep it alive until
/// the returned object is destroyed. Caller also retains ownership of
/// `error_reporter` and must ensure its lifetime is longer than the
/// FlatBufferModelBase instance.
/// Returns a nullptr in case of failure.
/// NOTE: this does NOT validate the buffer so it should NOT be called on
/// invalid/untrusted input. Use VerifyAndBuildFromBuffer in that case
static std::unique_ptr<T> BuildFromBuffer(
const char* caller_owned_buffer, size_t buffer_size,
ErrorReporter* error_reporter = T::GetDefaultErrorReporter()) {
error_reporter = ValidateErrorReporter(error_reporter);
std::unique_ptr<Allocation> allocation(
new MemoryAllocation(caller_owned_buffer, buffer_size, error_reporter));
return BuildFromAllocation(std::move(allocation), error_reporter);
}If I understand correctly, |
||
| NN_ERR_PRINTF("Context (model) non-initialized."); | ||
| return runtime_error; | ||
| } | ||
| if (tfl_ctx->models[g].model == NULL) { | ||
| NN_ERR_PRINTF("Context (tflite model) non-initialized."); | ||
| return runtime_error; | ||
| } | ||
| return success; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,7 +58,7 @@ wasm_load(char *model_name, graph *g, execution_target target) | |
| wasi_nn_error | ||
| wasm_load_by_name(const char *model_name, graph *g) | ||
| { | ||
| wasi_nn_error res = load_by_name(model_name, g); | ||
| wasi_nn_error res = load_by_name(model_name, strlen(model_name), g); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. better be #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
wasi_nn_error
wasm_load_by_name(const char *model_name, graph *g)
{
wasi_nn_error res = load_by_name(model_name, strlen(model_name), g);
return res;
}
#endif |
||
| return res; | ||
| } | ||
|
|
||
|
|
@@ -99,7 +99,11 @@ wasi_nn_error | |
| wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor, | ||
| uint32_t *out_size) | ||
| { | ||
| #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0 | ||
| return get_output(ctx, index, (uint8_t *)out_tensor, *out_size, out_size); | ||
| #else | ||
| return get_output(ctx, index, (uint8_t *)out_tensor, out_size); | ||
| #endif | ||
| } | ||
|
|
||
| float * | ||
|
|
@@ -108,7 +112,12 @@ run_inference(execution_target target, float *input, uint32_t *input_size, | |
| uint32_t num_output_tensors) | ||
| { | ||
| graph graph; | ||
|
|
||
| #if WASM_ENABLE_WASI_EPHEMERAL_NN == 0 | ||
| if (wasm_load(model_name, &graph, target) != success) { | ||
| #else | ||
| if (wasm_load_by_name(model_name, &graph) != success) { | ||
| #endif | ||
| NN_ERR_PRINTF("Error when loading model."); | ||
| exit(1); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @ayakoakasaka and @lum1n0us ,
For
wasi_nnandwasi_ephemeral_nn, different APIs need to be defined in the header file.However, currently using
wasi_ephemeral_nn, I find that I get an error when I callingset_input, ->Content is inconsistent when passed from wasm to native.So can we divide it into two PRs, first support
load_by_nameinwasi-nn, and then implement support forwasi_ephemeral_nnThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. As a workaround.