kazum commented on a change in pull request #5506:
URL: https://github.com/apache/incubator-tvm/pull/5506#discussion_r421331174
##########
File path: python/tvm/contrib/emcc.py
##########
@@ -44,25 +42,25 @@ def create_js(output,
The compile string.
"""
cmd = [cc]
- cmd += ["-Oz"]
- if not side_module:
- cmd += ["-s", "RESERVED_FUNCTION_POINTERS=2"]
- cmd += ["-s", "NO_EXIT_RUNTIME=1"]
- extra_methods = ['cwrap', 'getValue', 'setValue', 'addFunction']
- cfg = "[" + (','.join("\'%s\'" % x for x in extra_methods)) + "]"
- cmd += ["-s", "EXTRA_EXPORTED_RUNTIME_METHODS=" + cfg]
- else:
- cmd += ["-s", "SIDE_MODULE=1"]
- cmd += ["-o", output]
+ cmd += ["-O3"]
+
+ cmd += ["-std=c++14"]
+ cmd += ["-s", "ERROR_ON_UNDEFINED_SYMBOLS=0"]
+ cmd += ["-s", "STANDALONE_WASM=1"]
+
Review comment:
By default, emcc generates a wasm file whose max memory size is 16 MB.
It is too small to use for deep learning. We should extend the size by adding
"-s TOTAL_MEMORY=[mem_size]" at least. Another way is adding "-s
ALLOW_MEMORY_GROWTH=1" and calling memory.grow() when necessary. It looks hard
to implement, but we can avoid hard-coding the maximum memory size.
##########
File path: web/Makefile
##########
@@ -0,0 +1,51 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+TVM_ROOT=$(shell cd ..; pwd)
+
+INCLUDE_FLAGS = -I$(TVM_ROOT) -I$(TVM_ROOT)/include\
+ -I$(TVM_ROOT)/3rdparty/dlpack/include
-I$(TVM_ROOT)/3rdparty/dmlc-core/include
+
+.PHONY: clean all
+
+all: dist/wasm/tvmjs_runtime.wasm dist/wasm/tvmjs_runtime.wasi.js
+
+EMCC = emcc
+
+EMCC_CFLAGS = $(INCLUDE_FLAGS) -O3 -std=c++14 -Wno-ignored-attributes \
+ -s STANDALONE_WASM=1 -s ERROR_ON_UNDEFINED_SYMBOLS=0
+
+EMCC_LDFLAGS = --pre-js emcc/preload.js
+
+dist/wasm/%.bc: emcc/%.cc
+ @mkdir -p $(@D)
+ $(EMCC) $(EMCC_CFLAGS) -c -MM -MT dist/wasm/$*.bc $< >dist/wasm/$*.d
+ $(EMCC) $(EMCC_CFLAGS) -c -o dist/wasm/$*.bc $<
+
+
+dist/wasm/tvmjs_runtime.wasm: dist/wasm/wasm_runtime.bc
dist/wasm/tvmjs_support.bc
+ @mkdir -p $(@D)
+ $(EMCC) $(EMCC_CFLAGS) -o dist/wasm/tvmjs_runtime.js $+ $(EMCC_LDFLAGS)
+
+
+dist/wasm/tvmjs_runtime.wasi.js: dist/wasm/tvmjs_runtime.wasm
emcc/decorate_as_wasi.py
+ python3 emcc/decorate_as_wasi.py dist/wasm/tvmjs_runtime.js $@
Review comment:
Can we use --js-transform option to call decorate_as_wasi.py? Or
perhaps, it might be enough to use --pre-js and --post-js options to decorate
the output js.
##########
File path: web/README.md
##########
@@ -15,163 +15,70 @@
<!--- specific language governing permissions and limitations -->
<!--- under the License. -->
-# TVM WebAssembly and Javascript Backend
+# TVM WebAssembly Runtime
-This folder contains TVM WebAssembly and Javascript backend through Emscripten.
+This folder contains TVM WebAssembly Runtime.
## Installation
-While the LLVM main branch support webassembly as a target. We still need a
good runtime with libc and other
-system library support. Emscripten toolchain offers that nicely. The general
idea is to build TVM against
-the fastcomp LLVM backend in the Emscripten project and allow us to generate
```asmjs-unknown-emscripten```
-as a backend target.
+
+The LLVM main branch support webassembly as a target, we can directly
+build TVM with LLVM mainline to generate wasm modules.
+Note that, however, we still need emscripten to compile the runtime and
provide system library support.
+
+Note that so far we requires everything to be in the source and setup
PYTHONPATH(instead of use setup.py install).
### Setup Emscripten
-Checkout [Emscripten Portable SDK
Downloads](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html)
-to download emsdk-portable and unzip it on a local folder. Follow the
installation guide from emscripten document.
-```bash
-./emsdk update
-./emsdk install latest
-./emsdk activate latest
-```
+We use emscripten to compile our runtime wasm library as well as a WASI
variant that we can deploy
+to the browser environment.
-Because we need to compile against the LLVM backend of emscripten, we will
need the source and llvm library.
-Which can be installed via following command.
+Follow [Emscripten](https://emscripten.org/) to download emsdk and install
emcc on your local environment.
-```bash
-./emsdk install clang-incoming-64bit
-./emsdk activate clang-incoming-64bit
-```
+### Build TVM Wasm Runtime
-### Setup Environment Variable
+After the emcc is setup correctly. We can build tvm's wasm runtime by typing
`make` in the web folder.
-In normal setting, we can setup the necessary environment variable with the
following command.
```bash
-source /path-to-emsdk-portable/emsdk_env.sh
+make
```
-However, this will put emscripten's clang and llvm path ahead of the current
system path.
-What you can do is to set the path manually, by putting emscripten's path
after the PATH like the following ones.
-You can get the detailed path by type ```./emsdk activate```
-```bash
-export PATH=${PATH}:/emsdk-related-path-here
+This command will create the follow files:
+- `dist/wasm/libtvm_runtime.bc` bitcode library `tvm.contrib.emcc` will link
into.
+- `dist/wasm/tvmjs_runtime.wasm` a standalone wasm runtime for testing
purposes.
+- `dist/wasm/tvmjs_runtime.wasi.js` a WASI compatible library generated by
emscripten that can be fed into runtime.
-```
-### Build TVM with Fastcomp LLVM
+### Build TVM Wasm JS Frontend
-To build TVM with Emscripten's Fastcomp LLVM, we can modify the LLVM_CONFIG in
```config.mk```
-to point to fastcomp's llvm-config and build TVM normally.
+Type the following command in the web folder.
```bash
-LLVM_CONFIG =
/path/to/emsdk-portable/clang/fastcomp/build_incoming_64/bin/llvm-config
+npm run bundle
Review comment:
I think `npm install` should be added to resolve dependencies.
##########
File path: web/apps/node/wasi_rpc_server.js
##########
@@ -17,17 +17,20 @@
* under the License.
*/
-// Javascript RPC server example
-// Start and connect to websocket proxy.
+/**
+ * Example code to start the RPC server on nodejs using WAIS
Review comment:
WAIS => WASI
##########
File path: web/emcc/wasm_runtime.cc
##########
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * \file wasm_runtime.cc
+ * \brief TVM wasm runtime library pack.
+ */
+
+// configurations for the dmlc log.
+#define DMLC_LOG_CUSTOMIZE 0
+#define DMLC_LOG_STACK_TRACE 0
+#define DMLC_LOG_DEBUG 0
+#define DMLC_LOG_NODATE 1
+#define DMLC_LOG_FATAL_THROW 0
+
+#include <tvm/runtime/c_runtime_api.h>
+#include <dmlc/logging.h>
+
+#include "src/runtime/c_runtime_api.cc"
+#include "src/runtime/cpu_device_api.cc"
+#include "src/runtime/workspace_pool.cc"
+#include "src/runtime/library_module.cc"
+#include "src/runtime/system_library.cc"
+
+#include "src/runtime/module.cc"
+#include "src/runtime/ndarray.cc"
+#include "src/runtime/object.cc"
+#include "src/runtime/registry.cc"
+#include "src/runtime/file_util.cc"
+#include "src/runtime/graph/graph_runtime.cc"
+#include "src/runtime/rpc/rpc_session.cc"
+#include "src/runtime/rpc/rpc_endpoint.cc"
+#include "src/runtime/rpc/rpc_event_impl.cc"
+#include "src/runtime/rpc/rpc_channel.cc"
+#include "src/runtime/rpc/rpc_local_session.cc"
+#include "src/runtime/rpc/rpc_module.cc"
+
+
+// --- Implementations of backend and wasm runtime API. ---
+
+int TVMBackendParallelLaunch(FTVMParallelLambda flambda,
+ void* cdata,
+ int num_task) {
+ TVMAPISetLastError("Parallel is not supported in Web runtime");
+ return -1;
Review comment:
Can we simply launch a single task here like as follows?
```
TVMParallelGroupEnv env;
env.num_task = 1;
flambda(0, &env, cdata);
return 0;
```
##########
File path: web/tests/python/websock_rpc_test.py
##########
@@ -22,45 +22,61 @@
import tvm
from tvm import te
-import os
from tvm import rpc
-from tvm.contrib import util, emscripten
+from tvm.contrib import util, emcc
import numpy as np
proxy_host = "localhost"
proxy_port = 9090
-def test_rpc_array():
+def test_rpc():
if not tvm.runtime.enabled("rpc"):
return
- # graph
- n = tvm.runtime.convert(1024)
+ # generate the wasm library
+ target = "llvm -target=wasm32-unknown-unknown-wasm -system-lib"
+ if not tvm.runtime.enabled(target):
+ raise RuntimeError("Target %s is not enbaled" % target)
+ n = te.var("n")
A = te.placeholder((n,), name='A')
B = te.compute(A.shape, lambda *i: A(*i) + 1.0, name='B')
s = te.create_schedule(B.op)
- remote = rpc.connect(proxy_host, proxy_port, key="js")
- target = "llvm -target=asmjs-unknown-emscripten -system-lib"
- def check_remote():
- if not tvm.runtime.enabled(target):
- print("Skip because %s is not enabled" % target)
- return
- temp = util.tempdir()
+
+ fadd = tvm.build(s, [A, B], target, name="addone")
+ temp = util.tempdir()
+
+ wasm_path = temp.relpath("addone.wasm")
+ fadd.export_library(wasm_path, emcc.create_tvmjs_wasm)
+
+ wasm_binary = open(wasm_path, "rb").read()
+
+ remote = rpc.connect(proxy_host, proxy_port, key="wasm",
+ session_constructor=["rpc.WasmSession", wasm_binary])
Review comment:
session_constructor => session_constructor_args
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]