Ver Fonte

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

Wenyong Huang há 4 anos atrás
pai
commit
1a4aa5ac2f

+ 25 - 8
core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c

@@ -542,24 +542,24 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
     uint32 thread_handle;
     int32 ret = -1;
 #if WASM_ENABLE_LIBC_WASI != 0
-    WASIContext *wasi_ctx = get_wasi_ctx(module_inst);
+    WASIContext *wasi_ctx;
 #endif
 
     bh_assert(module);
+    bh_assert(module_inst);
 
     if (!(new_module_inst =
             wasm_runtime_instantiate_internal(module, true, 8192, 0,
                                               NULL, 0)))
         return -1;
 
-    if (module_inst) {
-        /* Set custom_data to new module instance */
-        wasm_runtime_set_custom_data_internal(
-            new_module_inst,
-            wasm_runtime_get_custom_data(module_inst));
-    }
+    /* Set custom_data to new module instance */
+    wasm_runtime_set_custom_data_internal(
+        new_module_inst,
+        wasm_runtime_get_custom_data(module_inst));
 
 #if WASM_ENABLE_LIBC_WASI != 0
+    wasi_ctx = get_wasi_ctx(module_inst);
     if (wasi_ctx)
         wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
 #endif
@@ -628,7 +628,7 @@ pthread_join_wrapper(wasm_exec_env_t exec_env, uint32 thread,
 
     /* validate addr, we can use current thread's
         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,
             do not spread exception here */
         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;
 }
 
+/* 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)  \
     { #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_getspecific,    "(i)i"),
     REG_NATIVE_FUNC(pthread_key_delete,     "(i)i"),
+    REG_NATIVE_FUNC(posix_memalign,         "(*ii)i"),
 };
 
 uint32

+ 6 - 1
core/iwasm/libraries/thread-mgr/thread_manager.c

@@ -659,6 +659,7 @@ void
 wasm_cluster_spread_exception(WASMExecEnv *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);
 }
@@ -677,7 +678,11 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
                                 void *custom_data)
 {
     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,
                   set_custom_data_visitor,

+ 12 - 0
doc/pthread_library.md

@@ -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
 ```
 
+**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**
 
 You can build the wasm module into AoT module with pthread support, please pass option `--enable-multi-thread` to wamrc:

+ 53 - 55
doc/wasm_c_api.md

@@ -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
 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.
 
-Supported APIs:
+a summary of unsupported APIs
+
+- Configuration
+
+``` c
+WASM_API_EXTERN own wasm_config_t* wasm_config_new(void);
+```
+
+- References
 
 ``` c
-/* wasm_bytevec_t APIs ... */
-
-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 */
+WASM_API_EXTERN bool wasm_##name##_same(const wasm_##name##_t*, const wasm_##name##_t*); \
+WASM_API_EXTERN void* wasm_##name##_get_host_info(const wasm_##name##_t*); \
+WASM_API_EXTERN void wasm_##name##_set_host_info(wasm_##name##_t*, void*); \
+WASM_API_EXTERN void wasm_##name##_set_host_info_with_finalizer( \
+WASM_API_EXTERN wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t*); \
+WASM_API_EXTERN wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t*); \
+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*);
 ```
 
-Unsupported APIs:
+- Frames
 
 ``` c
-/* wasm_tabletype_t APIs */
-/* wasm_memorytype_t APIs */
-/* wasm_externtype_t APIs */
-/* wasm_importtype_t APIs */
-/* wasm_exporttype_t APIs */
-/* wasm_ref_t APIs */
-/* wasm_shared_##name##_t APIs */
+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 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 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);
+```
+
+- Table Operations APIs
 
-/* wasm_table_t APIs */
-/* wasm_memory_t 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);
+```

+ 3 - 1
samples/workload/tensorflow/README.md

@@ -17,7 +17,9 @@ Then run
 ./build.sh
 # for linux platform, or
 ./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:
 - hack emcc to delete some objects in libc.a

+ 11 - 3
samples/workload/tensorflow/build.sh

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

+ 4 - 4
samples/workload/tensorflow/tf_lite.patch

@@ -19,14 +19,14 @@ index c7ddff58440..ebfebaead35 100644
  endif # ifeq ($(HOST_OS),$(TARGET))
  endif
  
-+CFLAGS+=-msimd128
-+CXXFLAGS+=-msimd128
++CFLAGS+=-msimd128 -mbulk-memory -matomics
++CXXFLAGS+=-msimd128 -mbulk-memory -matomics
 +
-+LIBFLAGS += -s TOTAL_STACK=1048576 \
++LIBFLAGS += -s TOTAL_STACK=1048576 -s MALLOC="none" \
 +            -s INITIAL_MEMORY=16777216 \
 +            -s MAXIMUM_MEMORY=167772160 \
 +            -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
 +
  # This library is the main target for this makefile. It will contain a minimal