Skip to content

[Bug] TVM MIPS32 .so Model Load Failure – ONNX Model Converted to MIPS32 Fails to Load with TVM Runtime #17805

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

Open
Leo5050xvjf opened this issue Apr 3, 2025 · 0 comments
Labels
needs-triage PRs or issues that need to be investigated by maintainers to find the right assignees to address it type: bug

Comments

@Leo5050xvjf
Copy link

Leo5050xvjf commented Apr 3, 2025

Expected behavior

I expect model.so (a TVM-compiled model for MIPS32) to be successfully loaded using dlopen or TVMModLoadFromFile on my MIPS32 development board, given that libtvm_runtime.so loads and runs correctly

Actual behavior

  • libtvm_runtime.so (v0.18.0) loads successfully on the MIPS32 board and executes basic runtime tests.
  • However, model.so fails to load with dlopen:
    Failed to load: /path/to/model.so: cannot open shared object file: No such file or directory
    
  • Same error occurs with TVMModLoadFromFile, even though the file exists at that path and has correct permissions.

Environment

Operating System:

  • Host: Ubuntu 20.04, x86_64
  • Target: MIPS32-based development board

TVM Version: v0.18.0

Compiler:

  • Host: GCC (x86_64)
  • Target: MIPS cross-compiler (mips-linux-gnu-gcc, GCC 7.2.0, glibc 2.29)

TVM Build Configuration:

x86_64 (Host)

#build on x86 PC
cd /path/to/tvm
git checkout v0.18.0
mkdir build-x86_64 && cd build-x86_64
cmake -DCMAKE_BUILD_TYPE=Release -DUSE_LLVM=ON ..
make -j4
  • Output: libtvm.so

MIPS32 (Target)

mips32el-toolchain.cmake.cmake

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR mipsel)
set(CMAKE_C_COMPILER /opt/mips-gcc720-glibc229/bin/mips-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER /opt/mips-gcc720-glibc229/bin/mips-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
#build on x86 PC
cd /path/to/tvm
git checkout v0.18.0
mkdir build-mips32 && cd build-mips32
cmake \
  -DCMAKE_TOOLCHAIN_FILE=../mips32el-toolchain.cmake \
  -DCMAKE_BUILD_TYPE=Release \
  -DUSE_LLVM=OFF \
  -DUSE_RPC=OFF \
  -DUSE_GRAPH_EXECUTOR=OFF \
  -DUSE_PROFILER=OFF \
  -DUSE_LIBBACKTRACE=OFF \
  ..
make -j4
  • Output: libtvm_runtime.so

Cross-Compilation for Model

Python script (generate_onnx.py)

import torch
import torch.nn as nn
import torch.onnx


class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 16, 3)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(16, 32, 3)
        self.fc1 = nn.Linear(32 * 5 * 5, 10)

    def forward(self, x):
        x = self.pool(torch.relu(self.conv1(x)))
        x = self.pool(torch.relu(self.conv2(x)))
        x = x.view(-1, 32 * 5 * 5)  
        x = self.fc1(x)
        return x


model = SimpleCNN()
model.eval()

dummy_input = torch.randn(1, 1, 28, 28)


torch.onnx.export(model, dummy_input, "model.onnx", 
                  input_names=["input"], output_names=["output"], 
                  opset_version=11)

print("ONNX model exported as 'model.onnx'")

Python script (generate_so.py)

import tvm
from tvm import relay
import onnx
from tvm.contrib import graph_executor
import tvm.contrib.cc as cc

onnx_model = onnx.load("model.onnx")
input_shape = (1, 1, 28, 28)
mod, params = relay.frontend.from_onnx(onnx_model, {"input": input_shape})

target = "llvm -mtriple=mipsel-linux-gnu -mcpu=mips32r2"

with tvm.transform.PassContext(opt_level=3):
    lib = relay.build(mod, target=target, params=params)

cross_compiler = cc.cross_compiler(
    "/path/to/mips-gcc720-glibc229/bin/mips-linux-gnu-gcc",
    options=["-mfp32", "-mnan=legacy"]
)
lib.export_library("model.so", fcompile=cross_compiler)
  • Flags: -mfp32 -mnan=legacy

Steps to reproduce

C Test: test_dlopen.c

#include <dlfcn.h>
#include <stdio.h>

int main() {
    void* handle = dlopen("/path/to/model.so", RTLD_LAZY);
    if (!handle) {
        printf("Failed to load: %s\n", dlerror());
        return -1;
    }
    printf("Loaded successfully\n");
    dlclose(handle);
    return 0;
}
  • Compile:
/path/to/mips-gcc720-glibc229/bin/mips-linux-gnu-gcc -o test_dlopen test_dlopen.c -ldl

C++ Test: test_tvm_runtime.cpp

#include <tvm/runtime/c_runtime_api.h>
#include <iostream>

int main() {
    std::cout << "TVM Runtime Version: " << TVM_VERSION << std::endl;
    TVMAPISetLastError("Test error message");
    const char* error = TVMGetLastError();
    std::cout << "Last Error: " << (error ? error : "None") << std::endl;
    std::cout << "Test completed successfully!" << std::endl;
    return 0;
}
  • Compile:
/path/to/mips-gcc720-glibc229/bin/mips-linux-gnu-g++ -o test_tvm_runtime test_tvm_runtime.cpp \
    -I /path/to/tvm/include \
    -I /path/to/tvm/3rdparty/dlpack/include \
    -I /path/to/tvm/3rdparty/dmlc-core/include \
    -L /path/to/tvm/build-mips32 \
    -ltvm_runtime -pthread -std=c++17

Deploy and Run on MIPS32

cd /path/to/XXX
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/XXX
chmod +x test_dlopen test_tvm_runtime

./test_tvm_runtime   # Works fine
./test_dlopen        # Fails

Output

test_tvm_runtime:
TVM Runtime Version: 0.18.0
Last Error: Test error message
Test completed successfully!

test_dlopen:
Failed to load: /path/to/XXX/model.so: cannot open shared object file: No such file or directory

More Info

file model.so 
model.so: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, with debug_info, not stripped
file libtvm_runtime.so
libtvm_runtime.so: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, with debug_info, not stripped
file libtvm.so
libtvm.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, BuildID[sha1]=ac5555851eefd24f951e85366f8fd0a5c95987d3, not stripped
If running on a PC x86 platform, the model.so can be successfully loaded and executed.

Triage

compilation

target:mips

component:runtime

area:relay

bug

@Leo5050xvjf Leo5050xvjf added needs-triage PRs or issues that need to be investigated by maintainers to find the right assignees to address it type: bug labels Apr 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-triage PRs or issues that need to be investigated by maintainers to find the right assignees to address it type: bug
Projects
None yet
Development

No branches or pull requests

1 participant