Enable multi-thread for tensorflow sample, update wasm-c-api document (#651)

This commit is contained in:
Wenyong Huang 2021-06-14 08:58:32 +08:00 committed by GitHub
parent 5d9597f064
commit 1a4aa5ac2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 115 additions and 73 deletions

View File

@ -542,24 +542,24 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
uint32 thread_handle; uint32 thread_handle;
int32 ret = -1; int32 ret = -1;
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
WASIContext *wasi_ctx = get_wasi_ctx(module_inst); WASIContext *wasi_ctx;
#endif #endif
bh_assert(module); bh_assert(module);
bh_assert(module_inst);
if (!(new_module_inst = if (!(new_module_inst =
wasm_runtime_instantiate_internal(module, true, 8192, 0, wasm_runtime_instantiate_internal(module, true, 8192, 0,
NULL, 0))) NULL, 0)))
return -1; return -1;
if (module_inst) { /* Set custom_data to new module instance */
/* Set custom_data to new module instance */ wasm_runtime_set_custom_data_internal(
wasm_runtime_set_custom_data_internal( new_module_inst,
new_module_inst, wasm_runtime_get_custom_data(module_inst));
wasm_runtime_get_custom_data(module_inst));
}
#if WASM_ENABLE_LIBC_WASI != 0 #if WASM_ENABLE_LIBC_WASI != 0
wasi_ctx = get_wasi_ctx(module_inst);
if (wasi_ctx) if (wasi_ctx)
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx); wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
#endif #endif
@ -628,7 +628,7 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread,
/* validate addr, we can use current thread's /* validate addr, we can use current thread's
module instance here as the memory is shared */ module instance here as the memory is shared */
if (!validate_app_addr(retval_offset, sizeof(void *))) { if (!validate_app_addr(retval_offset, sizeof(int32))) {
/* Join failed, but we don't want to terminate all threads, /* Join failed, but we don't want to terminate all threads,
do not spread exception here */ do not spread exception here */
wasm_runtime_set_exception(module_inst, NULL); wasm_runtime_set_exception(module_inst, NULL);
@ -1046,6 +1046,22 @@ pthread_key_delete_wrapper(wasm_exec_env_t exec_env, int32 key)
return 0; return 0;
} }
/* Currently the memory allocator doesn't support alloc specific aligned
space, we wrap posix_memalign to simply malloc memory */
static int32
posix_memalign_wrapper(wasm_exec_env_t exec_env,
void **memptr, int32 align, int32 size)
{
wasm_module_inst_t module_inst = get_module_inst(exec_env);
void *p = NULL;
*((int32 *)memptr) = module_malloc(size, (void**)&p);
if (!p)
return -1;
return 0;
}
#define REG_NATIVE_FUNC(func_name, signature) \ #define REG_NATIVE_FUNC(func_name, signature) \
{ #func_name, func_name##_wrapper, signature, NULL } { #func_name, func_name##_wrapper, signature, NULL }
@ -1069,6 +1085,7 @@ static NativeSymbol native_symbols_lib_pthread[] = {
REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"), REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"),
REG_NATIVE_FUNC(pthread_getspecific, "(i)i"), REG_NATIVE_FUNC(pthread_getspecific, "(i)i"),
REG_NATIVE_FUNC(pthread_key_delete, "(i)i"), REG_NATIVE_FUNC(pthread_key_delete, "(i)i"),
REG_NATIVE_FUNC(posix_memalign, "(*ii)i"),
}; };
uint32 uint32

View File

@ -659,6 +659,7 @@ void
wasm_cluster_spread_exception(WASMExecEnv *exec_env) wasm_cluster_spread_exception(WASMExecEnv *exec_env)
{ {
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
bh_assert(cluster);
traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env); traverse_list(&cluster->exec_env_list, set_exception_visitor, exec_env);
} }
@ -677,7 +678,11 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
void *custom_data) void *custom_data)
{ {
WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst); WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env); WASMCluster *cluster = NULL;
bh_assert(exec_env);
cluster = wasm_exec_env_get_cluster(exec_env);
bh_assert(cluster);
traverse_list(&cluster->exec_env_list, traverse_list(&cluster->exec_env_list,
set_custom_data_visitor, set_custom_data_visitor,

View File

@ -78,6 +78,18 @@ Then build the program with this command:
# -Wl,--no-check-features: the errno.o in wasi-sysroot is not compatible with pthread feature, pass this option to avoid errors # -Wl,--no-check-features: the errno.o in wasi-sysroot is not compatible with pthread feature, pass this option to avoid errors
``` ```
**Build with EMCC**
EMCC's `-pthread` option is not compatible with standalone mode, we need to pass `-mbulk-memory -matomics` to the compiler and `--shared-memory,--no-check-features` to linker manually
``` bash
emcc -O3 -mbulk-memory -matomics -s MALLOC="none" \
-Wl,--export=__data_end,--export=__heap_base \
-Wl,--shared-memory,--no-check-features \
-s ERROR_ON_UNDEFINED_SYMBOLS=0 \
main.c -o test.wasm
```
**Build AoT module** **Build AoT module**
You can build the wasm module into AoT module with pthread support, please pass option `--enable-multi-thread` to wamrc: You can build the wasm module into AoT module with pthread support, please pass option `--enable-multi-thread` to wamrc:

View File

@ -7,71 +7,69 @@ Every user should be familiar with *APIs* listed in
all [examples][https://github.com/WebAssembly/wasm-c-api/tree/master/example] are all [examples][https://github.com/WebAssembly/wasm-c-api/tree/master/example] are
very helpful for learning. very helpful for learning.
Currently, we support partial of *APIs* and are going to support the rest of Currently, we support partial of APIs and are going to support the rest of
them in next releases. them in next releases.
Supported APIs: a summary of unsupported APIs
- Configuration
``` c ``` c
/* wasm_bytevec_t APIs ... */ WASM_API_EXTERN own wasm_config_t* wasm_config_new(void);
wasm_engine_t *wasm_engine_new();
wasm_engine_t *wasm_engine_new_with_args(mem_alloc_type_t, const MemAllocOption*, runtime_mode_e);
void wasm_engine_delete(wasm_engine_t *);
wasm_store_t *wasm_store_new(wasm_engine_t *);
void wasm_store_delete(wasm_store_t *);
/* wasm_valtype_t APIs ... */
/* wasm_valtype_vec_t APIs ... */
/* wasm_functype_vec_t APIs ... */
/* wasm_globaltype_vec_t APIs ... */
/* wasm_val_t APIs ... */
/* wasm_trap_t partial APIs ... */
wasm_module_t *wasm_module_new(wasm_store_t *, const wasm_byte_vec_t *);
void wasm_module_delete(wasm_module_t *);
wasm_func_t *wasm_func_new(wasm_store_t *, const wasm_functype_t *, wasm_func_callback_t);
wasm_func_t *wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *, wasm_func_callback_with_env_t, void *env, void (*finalizer)(void *));
void wasm_func_delete(wasm_func_t *);
wasm_fucn_t *wasm_func_copy(const wasm_func_t *);
wasm_functype_t *wasm_func_type(const wasm_func_t *);
wasm_trap_t * wasm_func_call(const wasm_func_t *, const wasm_val_t params[], wasm_val_t results[]);
size_t wasm_func_param_arity(const wasm_func_t *);
size_t wasm_func_result_arity(const wasm_func_t *);
wasm_global_t *wasm_global_new(wasm_store_t *, const wasm_globaltype_t *, const wasm_val_t *);
wasm_global_t * wasm_global_copy(const wasm_global_t *);
void wasm_global_delete(wasm_global_t *);
bool wasm_global_same(const wasm_global_t *, const wasm_global_t *);
void wasm_global_set(wasm_global_t *, const wasm_val_t *);
void wasm_global_get(const wasm_global_t *, wasm_val_t *out);
wasm_globaltype_t * wasm_global_type(const wasm_global_t *);
wasm_instance_t *wasm_instance_new(wasm_store_t *, const wasm_module_t *, const wasm_extern_t *const imports[], wasm_trap_t **traps);
void wasm_instance_delete(wasm_instance_t *);
void wasm_instance_exports(const wasm_instance_t *, wasm_extern_vec_t *out);
/* wasm_extern_t APIs */
``` ```
Unsupported APIs: - References
``` c ``` c
/* wasm_tabletype_t APIs */ WASM_API_EXTERN bool wasm_##name##_same(const wasm_##name##_t*, const wasm_##name##_t*); \
/* wasm_memorytype_t APIs */ WASM_API_EXTERN void* wasm_##name##_get_host_info(const wasm_##name##_t*); \
/* wasm_externtype_t APIs */ WASM_API_EXTERN void wasm_##name##_set_host_info(wasm_##name##_t*, void*); \
/* wasm_importtype_t APIs */ WASM_API_EXTERN void wasm_##name##_set_host_info_with_finalizer( \
/* wasm_exporttype_t APIs */ WASM_API_EXTERN wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \
/* wasm_ref_t APIs */ WASM_API_EXTERN wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \
/* wasm_shared_##name##_t APIs */ WASM_API_EXTERN const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t*); \
WASM_API_EXTERN const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t*);
WASM_API_EXTERN own wasm_shared_##name##_t* wasm_##name##_share(const wasm_##name##_t*); \
WASM_API_EXTERN own wasm_##name##_t* wasm_##name##_obtain(wasm_store_t*, const wasm_shared_##name##_t*);
```
- Frames
``` c
WASM_API_EXTERN own wasm_frame_t* wasm_frame_copy(const wasm_frame_t*);
WASM_API_EXTERN struct wasm_instance_t* wasm_frame_instance(const wasm_frame_t*);
WASM_API_EXTERN uint32_t wasm_frame_func_index(const wasm_frame_t*);
WASM_API_EXTERN size_t wasm_frame_func_offset(const wasm_frame_t*);
WASM_API_EXTERN size_t wasm_frame_module_offset(const wasm_frame_t*);
WASM_API_EXTERN own wasm_frame_t* wasm_trap_origin(const wasm_trap_t*);
WASM_API_EXTERN void wasm_trap_trace(const wasm_trap_t*, own wasm_frame_vec_t* out);
```
Foreign Objects
``` c
WASM_API_EXTERN own wasm_foreign_t* wasm_foreign_new(wasm_store_t*);
```
- Several Module APIs
``` c
WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary); WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);
WASM_API_EXTERN void wasm_module_imports(const wasm_module_t*, own wasm_importtype_vec_t* out);
WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out); WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
WASM_API_EXTERN own wasm_module_t* wasm_module_deserialize(wasm_store_t*, const wasm_byte_vec_t*); WASM_API_EXTERN void wasm_module_serialize(const wasm_module_t*, own wasm_byte_vec_t* out);
```
/* wasm_table_t APIs */
/* wasm_memory_t APIs */ - Table Operations APIs
``` c
WASM_API_EXTERN own wasm_ref_t* wasm_table_get(const wasm_table_t*, wasm_table_size_t index);
WASM_API_EXTERN bool wasm_table_set(wasm_table_t*, wasm_table_size_t index, wasm_ref_t*);
WASM_API_EXTERN wasm_table_size_t wasm_table_size(const wasm_table_t*);
WASM_API_EXTERN bool wasm_table_grow(wasm_table_t*, wasm_table_size_t delta, wasm_ref_t* init);
```
- Memory Grow APIs
``` c
WASM_API_EXTERN bool wasm_memory_grow(wasm_memory_t*, wasm_memory_pages_t delta);
``` ```

View File

@ -17,7 +17,9 @@ Then run
./build.sh ./build.sh
# for linux platform, or # for linux platform, or
./build.sh --sgx ./build.sh --sgx
# for linux-sgx platform # for linux-sgx platform or
./build.sh --threads
# for multi-thread execution (on linux platform)
``` ```
to build tensorflow and run it with iwasm, which basically contains the following steps: to build tensorflow and run it with iwasm, which basically contains the following steps:
- hack emcc to delete some objects in libc.a - hack emcc to delete some objects in libc.a

View File

@ -1,10 +1,10 @@
#!/bin/bash
# #
# Copyright (C) 2019 Intel Corporation. All rights reserved. # Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# #
#!/bin/bash
#################################### ####################################
# build tensorflow-lite sample # # build tensorflow-lite sample #
#################################### ####################################
@ -99,6 +99,8 @@ WAMRC_CMD="$(pwd)/wamrc"
cd ${OUT_DIR} cd ${OUT_DIR}
if [[ $1 == '--sgx' ]]; then if [[ $1 == '--sgx' ]]; then
${WAMRC_CMD} --enable-simd -sgx -o benchmark_model.aot benchmark_model.wasm ${WAMRC_CMD} --enable-simd -sgx -o benchmark_model.aot benchmark_model.wasm
elif [[ $1 == '--threads' ]]; then
${WAMRC_CMD} --enable-simd --enable-multi-thread -o benchmark_model.aot benchmark_model.wasm
else else
${WAMRC_CMD} --enable-simd -o benchmark_model.aot benchmark_model.wasm ${WAMRC_CMD} --enable-simd -o benchmark_model.aot benchmark_model.wasm
fi fi
@ -137,7 +139,13 @@ else
IWASM_CMD="${WAMR_PLATFORM_DIR}/linux/build/iwasm" IWASM_CMD="${WAMR_PLATFORM_DIR}/linux/build/iwasm"
fi fi
${IWASM_CMD} --heap-size=10475860 \ if [[ $1 == '--threads' ]]; then
${IWASM_CMD} --heap-size=10475860 \
${OUT_DIR}/benchmark_model.aot --num_threads=4 \
--graph=mobilenet_quant_v1_224.tflite --max_secs=300
else
${IWASM_CMD} --heap-size=10475860 \
${OUT_DIR}/benchmark_model.aot \ ${OUT_DIR}/benchmark_model.aot \
--graph=mobilenet_quant_v1_224.tflite --max_secs=300 --graph=mobilenet_quant_v1_224.tflite --max_secs=300
fi

View File

@ -19,14 +19,14 @@ index c7ddff58440..ebfebaead35 100644
endif # ifeq ($(HOST_OS),$(TARGET)) endif # ifeq ($(HOST_OS),$(TARGET))
endif endif
+CFLAGS+=-msimd128 +CFLAGS+=-msimd128 -mbulk-memory -matomics
+CXXFLAGS+=-msimd128 +CXXFLAGS+=-msimd128 -mbulk-memory -matomics
+ +
+LIBFLAGS += -s TOTAL_STACK=1048576 \ +LIBFLAGS += -s TOTAL_STACK=1048576 -s MALLOC="none" \
+ -s INITIAL_MEMORY=16777216 \ + -s INITIAL_MEMORY=16777216 \
+ -s MAXIMUM_MEMORY=167772160 \ + -s MAXIMUM_MEMORY=167772160 \
+ -s ALLOW_MEMORY_GROWTH=1 \ + -s ALLOW_MEMORY_GROWTH=1 \
+ -Wl,--export=__data_end -Wl,--export=__heap_base \ + -Wl,--export=__data_end -Wl,--export=__heap_base,--shared-memory,--no-check-features \
+ -s ERROR_ON_UNDEFINED_SYMBOLS=0 + -s ERROR_ON_UNDEFINED_SYMBOLS=0
+ +
# This library is the main target for this makefile. It will contain a minimal # This library is the main target for this makefile. It will contain a minimal