因為 onnx 套件在 risc-v 上面沒法安裝,所以要在 x86 上面 cross-compile 模型
以下是編譯用的 python 檔,跟之前 x86 的差別為
riscv_fcompile 函數並增加到 ex.export_library(output_path, fcompile=riscv_fcompile)target="llvm" ,改成 target="c" ,原因是 llvm可以編譯的過,但到 inference 時會跳
TVMError: Binary was created using {relax.Executable} but a loader of that name is not registered. Available loaders are static_library, const_loader, c, relax.VMExecutable, bananapi. Perhaps you need to recompile with this runtime enabled.然後這份檔案會跳
# Metadata omitted. Use show_meta=True in script() method to show it.
Traceback (most recent call last):
File "/home/fre930727/whisper-tiny/onnx/compile_onnx_models_lack_of_parameters.py", line 80, in <module>
decoder_so = compile_model("decoder_model.onnx", target = tvm.target.Target("c"))
File "/home/fre930727/whisper-tiny/onnx/compile_onnx_models_lack_of_parameters.py", line 75, in compile_model
ex.export_library(output_path, fcompile=riscv_fcompile)
File "/home/fre930727/tvm/python/tvm/relax/vm_build.py", line 146, in export_library
return self.mod.export_library(
File "/home/fre930727/tvm/python/tvm/runtime/module.py", line 628, in export_library
return fcompile(file_name, files, **kwargs)
File "/home/fre930727/whisper-tiny/onnx/compile_onnx_models_lack_of_parameters.py", line 15, in riscv_fcompile
return cc.create_shared(
File "/home/fre930727/tvm/python/tvm/contrib/cc.py", line 94, in create_shared
_linux_compile(output, objects, options, cc, cwd, ccache_env, compile_shared=True)
File "/home/fre930727/tvm/python/tvm/contrib/cc.py", line 371, in _linux_compile
raise RuntimeError(msg)
RuntimeError: Compilation error:
/tmp/tmptt6npw2p/lib0.c:54:17: error: conflicting declaration of C function 'int32_t erf(void*, int32_t*, int32_t, void*, int32_t*, void*)'
54 | TVM_DLL int32_t erf(void* args, int32_t* arg_type_ids, int32_t num_args, void* out_ret_value, int32_t* out_ret_tcode, void* resource_handle);
| ^~~
In file included from /opt/riscv/sysroot/usr/include/features.h:524,
from /opt/riscv/sysroot/usr/include/bits/libc-header-start.h:33,
from /opt/riscv/sysroot/usr/include/stdint.h:26,
from /opt/riscv/lib/gcc/riscv64-unknown-linux-gnu/15.1.0/include/stdint.h:11,
from /home/fre930727/tvm/3rdparty/dlpack/include/dlpack/dlpack.h:35,
from /home/fre930727/tvm/include/tvm/runtime/c_runtime_api.h:79,
from /tmp/tmptt6npw2p/lib0.c:3:
/opt/riscv/sysroot/usr/include/bits/mathcalls.h:285:1: note: previous declaration 'double erf(double)'
285 | __MATHCALL_VEC (erf,, (_Mdouble_));
| ^~~~~~~~~~~~~~
/tmp/tmptt6npw2p/lib0.c:510:17: error: conflicting declaration of C function 'int32_t erf(void*, int32_t*, int32_t, void*, int32_t*, void*)'
510 | TVM_DLL int32_t erf(void* args, int32_t* arg_type_ids, int32_t num_args, void* out_ret_value, int32_t* out_ret_tcode, void* resource_handle) {
| ^~~
/opt/riscv/sysroot/usr/include/bits/mathcalls.h:285:1: note: previous declaration 'double erf(double)'
285 | __MATHCALL_VEC (erf,, (_Mdouble_));
| ^~~~~~~~~~~~~~
Command line: riscv64-unknown-linux-gnu-g++ -shared -fPIC -o decoder_model.so /tmp/tmptt6npw2p/lib0.c /tmp/tmptt6npw2p/devc.c -I/home/fre930727/tvm/include -I/home/fre930727/tvm/3rdparty/dlpack/include -I/home/fre930727/tvm/3rdparty/dmlc-core/include -march=rv64imafdcv -mabi=lp64d
重點是/tmp/tmptt6npw2p/lib0.c:54:17: error: conflicting declaration of C function 'int32_t erf(void*, int32_t*, int32_t, void*, int32_t*, void*)',好像撞名字了
再補充到,我剛剛用以下的 script 去改 node 名稱,但仍報一樣的錯
import onnx
# Load ONNX model
onnx_model = onnx.load("decoder_model.onnx")
# Add prefix to every node name
for node in onnx_model.graph.node:
node.name = "ccucsie_" + node.name if node.name else "ccucsie_unnamed"
print("hi")
# Save modified model
onnx.save(onnx_model, "decoder_model_renamed.onnx")
完整的編譯檔案
import onnx
import tvm
from tvm import relax
from tvm.relax.frontend.onnx import from_onnx # Correct import path
from tvm.relax.dpl import is_op, wildcard
from tvm.contrib import cc
def riscv_fcompile(file_name, files, options=None, **kwargs):
if options is None:
options = []
# 添加任何必要的 RISC-V 編譯選項,例如浮點 ABI
options.append("-march=rv64imafdcv") # 範例,指定 ISA 擴展
options.append("-mabi=lp64d") # 範例,指定 ABI
return cc.create_shared(
file_name,
files,
options=options,
cc="riscv64-unknown-linux-gnu-g++", # 指定你的 RISC-V 編譯器
**kwargs
)
def compile_model(onnx_path, target="llvm"):
# 1. Load ONNX model
onnx_model = onnx.load(onnx_path)
# 2. Convert to Relax IR (updated API)
#mod = from_onnx(onnx_model, {"input_features": (1, 80, 3000)})# give input shape of both encoder and decoder, make them static. Somer op does not support dynamic shape
mod = from_onnx(onnx_model, {"input_ids": (1, 1), "encoder_hidden_states": (1, 1500, 384)})# give input shape of both encoder and decoder, make them static. Somer op does not support dynamic shape
#mod = from_onnx(onnx_model)
#mod=tvm.relax.transform.BindSymbolicVars({"batch_size":1, "encoder_sequence_length_out": 1500})(mod)
patterns = [("bananapi.matmul", is_op("relax.matmul")(wildcard(), wildcard()))]
#patterns = [("tensorrt.add", is_op("relax.add")(wildcard(), wildcard()))]
'''
annotate_codegen: 不要 Merge 相鄰的 OP,一個 OP 一個 Relax function
bind_constants: 綁定常數,如果前面 from_onnx 的 keep_params_in_input=False(預設) 這裡要設成 bind_constants=False
如果前面 from_onnx 的 keep_params_in_input=True 這裡要設成 bind_constants=True(預設)
'''
mod = relax.transform.FuseOpsByPattern(patterns, bind_constants=False, annotate_codegen=True)(mod)
#mod = relax.transform.FuseOpsByPattern(patterns, bind_constants=False)(mod)
#mod = relax.transform.FuseOpsByPattern(patterns)(mod)
#mod.show()
#mod = relax.transform.MergeCompositeFunctions()(mod)
#mod.show()
mod = relax.transform.RunCodegen()(mod)
mod.show()
# 3. Apply mandatory passes
seq = tvm.ir.transform.Sequential([
relax.transform.LegalizeOps(),
relax.transform.FoldConstant(),
relax.transform.DeadCodeElimination()
])
mod = seq(mod)
# Check if output IRModule is well-formed.
#assert relax.analysis.well_formed(mod)
# 4. Build
ex = relax.build(mod, target)
# 5. Save
output_path = onnx_path.replace(".onnx", ".so")
ex.export_library(output_path, fcompile=riscv_fcompile)
return output_path
# Compile both encoder and decoder
#encoder_so = compile_model("encoder_model.onnx", target="llvm -mtriple=riscv64-unknown-linux-gnu -mattr=+m,+a,+f,+d,+cllvm")
decoder_so = compile_model("decoder_model.onnx", target = tvm.target.Target("c"))
riscv toolchain cross-check
zin’s simple.so cant work here