Enable e2e tests (#29)
* Sync with latest MLIR. * Enable ONNX backend tests as a means to test ONNF lowering end-to-end. * Install ONNX using quiet mode. * Remove debug comments. * Install ONNX from third_party/onnx. * Check python version and fix pip command for installing ONNX. * Using --user install option to prevent permission denied. * Remove unused imports. * Try using stock ONNX pip package as there are more tests in them. * Pip got stuck building wheels, try sudo. * Use verbose install to debug. * Invalidate cache to build LLVM tools. * Fix mlir installation script location. * Debug to locate ONNF. * Sanity check. * Check out ONNF code first. * Use verbose LIT output. * 1. Update documentation to always use verbose LIT. 2. Update krnl ops to reflect new affine map attribute syntax. * See if conda exists * Install ONNX by manually cloning the repo. * Install cmake first. * Using sudo priviledge when installing. * Limit build parallelism. * Limit parallelism. * Larger memory. * Install onnx package with pip. * Build MLIR tools. * Invalidate cache. * Compile model.so with -fPIC. * Remove module dump to get concise debug output. * Print command before executing. * Use quiet install mode to reduce logging. * Use -relocation-model=pic to generate position independent code. * 1. Remove MAKEFLAGS because now buildbot has enough memory. 2. Run DocCheck as a last step. * 1. Add verbose mode for backtend test. * When dumping to LLVM bitcode, do not dump module IR, but print a message indicating that bitcode has been written to disk. * Do not pass MakeFlags to CMake. * Add more explaination for posible reasons of failing to identify tests.
This commit is contained in:
parent
c2d31c0b78
commit
8665ecd998
|
@ -3,27 +3,12 @@ jobs:
|
||||||
build:
|
build:
|
||||||
docker:
|
docker:
|
||||||
- image: circleci/python
|
- image: circleci/python
|
||||||
|
resource_class: medium+
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- run:
|
- run:
|
||||||
name: Installing GCC, CMake, Ninja, Protobuf
|
name: Installing GCC, CMake, Ninja, Protobuf
|
||||||
command: sudo apt-get update && sudo apt-get install -y gcc g++ cmake ninja-build protobuf-compiler
|
command: sudo apt-get update && sudo apt-get install -y gcc g++ cmake ninja-build protobuf-compiler
|
||||||
# Use cached mlir installation if possible.
|
|
||||||
- restore_cache:
|
|
||||||
key: V2-LLVM-PROJECT-{{ arch }}
|
|
||||||
- run:
|
|
||||||
name: Install MLIR
|
|
||||||
command: |
|
|
||||||
# Check whether cache restoration succeeds by checking whether
|
|
||||||
# mlir-opt executable exists.
|
|
||||||
if [ ! -f llvm-project/build/bin/mlir-opt ]; then
|
|
||||||
export MAKEFLAGS=-j4
|
|
||||||
source utils/install-mlir.sh
|
|
||||||
fi
|
|
||||||
- save_cache:
|
|
||||||
key: V2-LLVM-PROJECT-{{ arch }}
|
|
||||||
paths:
|
|
||||||
- llvm-project
|
|
||||||
- checkout:
|
- checkout:
|
||||||
path: ONNF
|
path: ONNF
|
||||||
- run:
|
- run:
|
||||||
|
@ -31,9 +16,30 @@ jobs:
|
||||||
command: |
|
command: |
|
||||||
cd ONNF
|
cd ONNF
|
||||||
git submodule update --init --recursive
|
git submodule update --init --recursive
|
||||||
|
# Use cached mlir installation if possible.
|
||||||
|
- restore_cache:
|
||||||
|
key: V4-LLVM-PROJECT-{{ arch }}
|
||||||
|
- run:
|
||||||
|
name: Install MLIR
|
||||||
|
command: |
|
||||||
|
# Check whether cache restoration succeeds by checking whether
|
||||||
|
# mlir-opt executable exists.
|
||||||
|
if [ ! -f llvm-project/build/bin/mlir-opt ]; then
|
||||||
|
source ONNF/utils/install-mlir.sh
|
||||||
|
fi
|
||||||
|
- save_cache:
|
||||||
|
key: V4-LLVM-PROJECT-{{ arch }}
|
||||||
|
paths:
|
||||||
|
- llvm-project
|
||||||
- run:
|
- run:
|
||||||
name: Install ONNF
|
name: Install ONNF
|
||||||
command: source ONNF/utils/install-onnf.sh
|
command: source ONNF/utils/install-onnf.sh
|
||||||
|
- run:
|
||||||
|
name: Run End-To-End Tests
|
||||||
|
command: |
|
||||||
|
sudo pip install -q onnx
|
||||||
|
cd ONNF/build
|
||||||
|
cmake --build . --target run-onnx-backend-test
|
||||||
- run:
|
- run:
|
||||||
name: Run DocCheck
|
name: Run DocCheck
|
||||||
command: cd ONNF/build && cmake --build . --target check-doc
|
command: cd ONNF/build && cmake --build . --target check-doc
|
||||||
|
|
|
@ -27,4 +27,3 @@ set(CMAKE_CXX_STANDARD 14)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
add_subdirectory(doc)
|
add_subdirectory(doc)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,8 @@ cmake -G Ninja ../llvm \
|
||||||
-DLLVM_ENABLE_ASSERTIONS=ON \
|
-DLLVM_ENABLE_ASSERTIONS=ON \
|
||||||
-DLLVM_ENABLE_RTTI=ON
|
-DLLVM_ENABLE_RTTI=ON
|
||||||
|
|
||||||
cmake --build . --target check-mlir -- ${MAKEFLAGS}
|
cmake --build . --target
|
||||||
|
cmake --build . --target check-mlir
|
||||||
```
|
```
|
||||||
|
|
||||||
Two environment variables need to be set:
|
Two environment variables need to be set:
|
||||||
|
@ -42,6 +43,7 @@ cmake ..
|
||||||
cmake --build . --target onnf
|
cmake --build . --target onnf
|
||||||
|
|
||||||
# Run FileCheck tests:
|
# Run FileCheck tests:
|
||||||
|
export LIT_OPTS=-v
|
||||||
cmake --build . --target check-mlir-lit
|
cmake --build . --target check-mlir-lit
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -135,10 +135,13 @@ int main(int argc, char *argv[]) {
|
||||||
if (mlir::failed(pm.run(*module)))
|
if (mlir::failed(pm.run(*module)))
|
||||||
return 4;
|
return 4;
|
||||||
|
|
||||||
module->dump();
|
|
||||||
|
|
||||||
// Write LLVM bitcode to disk.
|
if (emissionTarget == EmitLLVMBC) {
|
||||||
if (emissionTarget == EmitLLVMBC)
|
// Write LLVM bitcode to disk.
|
||||||
EmitLLVMBitCode(module);
|
EmitLLVMBitCode(module);
|
||||||
|
printf("LLVM bitcode written to ./model.bc");
|
||||||
|
} else
|
||||||
|
module->dump();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
add_subdirectory(mlir)
|
add_subdirectory(mlir)
|
||||||
|
add_subdirectory(backend)
|
|
@ -0,0 +1,10 @@
|
||||||
|
configure_file(test.py test.py COPYONLY)
|
||||||
|
configure_file(test_config.py.in test_config.py)
|
||||||
|
|
||||||
|
find_package(PythonInterp 3 REQUIRED)
|
||||||
|
add_custom_target(run-onnx-backend-test
|
||||||
|
COMMAND ${PYTHON_EXECUTABLE}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/test.py)
|
||||||
|
|
||||||
|
add_dependencies(run-onnx-backend-test onnf)
|
||||||
|
add_dependencies(run-onnx-backend-test pyruntime)
|
|
@ -3,46 +3,51 @@ from __future__ import division
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import itertools
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
import onnx.backend.base
|
import onnx.backend.base
|
||||||
import onnx.backend.test
|
import onnx.backend.test
|
||||||
|
|
||||||
from onnx.backend.base import Device, DeviceType
|
from onnx.backend.base import Device, DeviceType
|
||||||
import onnx.shape_inference
|
|
||||||
import onnx.version_converter
|
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import test_config
|
||||||
|
|
||||||
|
VERBOSE = bool(os.environ.get("VERBOSE"))
|
||||||
|
|
||||||
|
CXX = test_config.CXX_PATH
|
||||||
|
ONNF = os.path.join(test_config.ONNF_BUILD_PATH, "bin/onnf")
|
||||||
|
LLC = os.path.join(test_config.LLVM_PROJ_BUILD_PATH, "bin/llc")
|
||||||
|
|
||||||
|
# Make lib folder under build directory visible in PYTHONPATH
|
||||||
|
doc_check_base_dir = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
RUNTIME_DIR = os.path.join(test_config.ONNF_BUILD_PATH, "lib")
|
||||||
|
sys.path.append(RUNTIME_DIR)
|
||||||
from pyruntime import ExecutionSession
|
from pyruntime import ExecutionSession
|
||||||
|
|
||||||
CXX = os.getenv('CXX')
|
|
||||||
ONNF = os.getenv('ONNF')
|
def execute_commands(cmds):
|
||||||
LLC = os.getenv('LLC')
|
if (VERBOSE):
|
||||||
RT_DIR = os.getenv('RT_DIR')
|
print(" ".join(cmds))
|
||||||
assert CXX and ONNF and LLC and RT_DIR, "tools path not set"
|
subprocess.run(cmds, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
class DummyBackend(onnx.backend.base.Backend):
|
class DummyBackend(onnx.backend.base.Backend):
|
||||||
@classmethod
|
@classmethod
|
||||||
def prepare(
|
def prepare(cls, model, device='CPU', **kwargs):
|
||||||
cls,
|
|
||||||
model,
|
|
||||||
device='CPU',
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
super(DummyBackend, cls).prepare(model, device, **kwargs)
|
super(DummyBackend, cls).prepare(model, device, **kwargs)
|
||||||
# Save model to disk as temp_model.onnx.
|
# Save model to disk as temp_model.onnx.
|
||||||
onnx.save(model, "temp_model.onnx")
|
onnx.save(model, "temp_model.onnx")
|
||||||
# Call frontend to process temp_model.onnx, bit code will be generated.
|
# Call frontend to process temp_model.onnx, bit code will be generated.
|
||||||
subprocess.run([ONNF, "temp_model.onnx"], stdout=subprocess.PIPE)
|
execute_commands([ONNF, "temp_model.onnx"])
|
||||||
# Call llc to generate object file from bitcode.
|
# Call llc to generate object file from bitcode.
|
||||||
subprocess.run([LLC, "-filetype=obj", "model.bc"],
|
execute_commands(
|
||||||
stdout=subprocess.PIPE)
|
[LLC, "-filetype=obj", "-relocation-model=pic", "model.bc"])
|
||||||
# Generate shared library from object file, linking with c runtime.
|
# Generate shared library from object file, linking with c runtime.
|
||||||
subprocess.run([
|
execute_commands([
|
||||||
CXX, "-shared", "model.o", "-o", "model.so", "-L" + RT_DIR,
|
CXX, "-shared", "-fPIC", "model.o", "-o", "model.so",
|
||||||
"-lcruntime"
|
"-L" + RUNTIME_DIR, "-lcruntime"
|
||||||
],
|
])
|
||||||
stdout=subprocess.PIPE)
|
|
||||||
return ExecutionSession("./model.so", "_dyn_entry_point_main_graph")
|
return ExecutionSession("./model.so", "_dyn_entry_point_main_graph")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -140,18 +145,15 @@ import inspect
|
||||||
all_tests = inspect.getmembers(
|
all_tests = inspect.getmembers(
|
||||||
backend_test.test_cases["OnnxBackendNodeModelTest"])
|
backend_test.test_cases["OnnxBackendNodeModelTest"])
|
||||||
all_test_names = list(map(lambda x: x[0], all_tests))
|
all_test_names = list(map(lambda x: x[0], all_tests))
|
||||||
|
|
||||||
|
# Ensure that test names specified in test_to_enable actually exist.
|
||||||
for test_name in test_to_enable:
|
for test_name in test_to_enable:
|
||||||
assert test_name in all_test_names, "test name {} not found".format(test_name)
|
assert test_name in all_test_names, "test name {} not found, it is likely "
|
||||||
|
"that you may have misspelled the test name or the specified test does not "
|
||||||
|
"exist in the version of onnx package you installed.".format(
|
||||||
|
test_name)
|
||||||
backend_test.include(r"^{}$".format(test_name))
|
backend_test.include(r"^{}$".format(test_name))
|
||||||
|
|
||||||
|
|
||||||
def tearDownModule():
|
|
||||||
print()
|
|
||||||
print("*" * 40)
|
|
||||||
print("A total of {} tests should have run".format(len(test_to_enable)))
|
|
||||||
print("*" * 40)
|
|
||||||
|
|
||||||
|
|
||||||
# import all test cases at global scope to make them visible to python.unittest
|
# import all test cases at global scope to make them visible to python.unittest
|
||||||
globals().update(backend_test.test_cases)
|
globals().update(backend_test.test_cases)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ONNF_BUILD_PATH = "@CMAKE_BINARY_DIR@"
|
||||||
|
LLVM_PROJ_BUILD_PATH = "@LLVM_PROJ_BUILD@"
|
||||||
|
CXX_PATH = "@CMAKE_CXX_COMPILER@"
|
|
@ -1,12 +1,12 @@
|
||||||
// RUN: onnf-opt %s -mlir-print-op-generic | FileCheck -check-prefix=GENERIC %s
|
// RUN: onnf-opt %s -mlir-print-op-generic | FileCheck -check-prefix=GENERIC %s
|
||||||
// RUN: onnf-opt %s | FileCheck %s
|
// RUN: onnf-opt %s | FileCheck %s
|
||||||
|
|
||||||
// GENERIC-DAG: #{{.*}} = () -> (0)
|
// GENERIC-DAG: #{{.*}} = affine_map<() -> (0)>
|
||||||
// GENERIC-DAG: #{{.*}} = () -> (10)
|
// GENERIC-DAG: #{{.*}} = affine_map<() -> (10)>
|
||||||
// GENERIC-DAG: #{{.*}} = () -> (1)
|
// GENERIC-DAG: #{{.*}} = affine_map<() -> (1)>
|
||||||
// GENERIC-DAG: #{{.*}} = () -> (11)
|
// GENERIC-DAG: #{{.*}} = affine_map<() -> (11)>
|
||||||
// GENERIC-DAG: #{{.*}} = (d0, d1) -> (d0 - d1)
|
// GENERIC-DAG: #{{.*}} = affine_map<(d0, d1) -> (d0 - d1)>
|
||||||
// GENERIC-DAG: #{{.*}} = (d0, d1) -> (d0 + d1)
|
// GENERIC-DAG: #{{.*}} = affine_map<(d0, d1) -> (d0 + d1)>
|
||||||
|
|
||||||
func @simple_iterate(%N : index) {
|
func @simple_iterate(%N : index) {
|
||||||
%ii, %ij, %ik = krnl.define_loops 3
|
%ii, %ij, %ik = krnl.define_loops 3
|
||||||
|
@ -55,18 +55,18 @@ func @affine_map_bound(%N : index) {
|
||||||
// GENERIC: "krnl.iterate"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) ( {
|
// GENERIC: "krnl.iterate"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) ( {
|
||||||
// GENERIC-NEXT: ^bb0(%{{.*}}: index, %{{.*}}: index):
|
// GENERIC-NEXT: ^bb0(%{{.*}}: index, %{{.*}}: index):
|
||||||
// CHECK: krnl.iterate(%{{.*}}, %{{.*}}) with (%{{.*}} -> %{{.*}} = 0 to 10, %{{.*}} -> %{{.*}} = 0 to 10) {
|
// CHECK: krnl.iterate(%{{.*}}, %{{.*}}) with (%{{.*}} -> %{{.*}} = 0 to 10, %{{.*}} -> %{{.*}} = 0 to 10) {
|
||||||
krnl.iterate(%oi, %oj) with (%ii -> %i = ()->(0)() to ()->(10)(), %ij -> %j = 0 to 10) {
|
krnl.iterate(%oi, %oj) with (%ii -> %i = affine_map<()->(0)>() to affine_map<()->(10)>(), %ij -> %j = 0 to 10) {
|
||||||
// GENERIC: "krnl.iterate"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) ( {
|
// GENERIC: "krnl.iterate"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) ( {
|
||||||
// GENERIC-NEXT: ^bb0(%{{.*}}: index):
|
// GENERIC-NEXT: ^bb0(%{{.*}}: index):
|
||||||
// CHECK: krnl.iterate(%{{.*}}) with (%{{.*}} -> %{{.*}} = #{{.*}}(%{{.*}}, %{{.*}}) to #{{.*}}(%{{.*}}, %{{.*}})) {
|
// CHECK: krnl.iterate(%{{.*}}) with (%{{.*}} -> %{{.*}} = #{{.*}}(%{{.*}}, %{{.*}}) to #{{.*}}(%{{.*}}, %{{.*}})) {
|
||||||
krnl.iterate(%ok) with (%ik -> %k = (d0, d1)->(d0 - d1)(%i, %j) to (d0, d1)->(d0 + d1)(%i, %j)) {
|
krnl.iterate(%ok) with (%ik -> %k = affine_map<(d0, d1)->(d0 - d1)>(%i, %j) to affine_map<(d0, d1)->(d0 + d1)>(%i, %j)) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GENERIC: "krnl.iterate"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) ( {
|
// GENERIC: "krnl.iterate"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) ( {
|
||||||
// GENERIC-NEXT: ^bb0(%{{.*}}: index):
|
// GENERIC-NEXT: ^bb0(%{{.*}}: index):
|
||||||
// CHECK: krnl.iterate(%{{.*}}) with (%{{.*}} -> %{{.*}} = max #map{{.*}}(%{{.*}}, %{{.*}}) to min #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}]) {
|
// CHECK: krnl.iterate(%{{.*}}) with (%{{.*}} -> %{{.*}} = max #map{{.*}}(%{{.*}}, %{{.*}}) to min #map{{.*}}(%{{.*}}, %{{.*}})[%{{.*}}]) {
|
||||||
krnl.iterate(%ok) with (%ik -> %k = max (d0, d1)->(d0 - d1, 0)(%i, %j) to min (d0, d1)[s0]->(d0 + d1, s0)(%i, %j)[%N]) {
|
krnl.iterate(%ok) with (%ik -> %k = max affine_map<(d0, d1)->(d0 - d1, 0)>(%i, %j) to min affine_map<(d0, d1)[s0]->(d0 + d1, s0)>(%i, %j)[%N]) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,4 +9,5 @@ cmake -G Ninja ../llvm \
|
||||||
-DLLVM_ENABLE_ASSERTIONS=ON \
|
-DLLVM_ENABLE_ASSERTIONS=ON \
|
||||||
-DLLVM_ENABLE_RTTI=ON
|
-DLLVM_ENABLE_RTTI=ON
|
||||||
|
|
||||||
cmake --build . --target check-mlir -- ${MAKEFLAGS}
|
cmake --build . --target
|
||||||
|
cmake --build . --target check-mlir
|
|
@ -7,4 +7,5 @@ cmake ..
|
||||||
cmake --build . --target onnf
|
cmake --build . --target onnf
|
||||||
|
|
||||||
# Run FileCheck tests:
|
# Run FileCheck tests:
|
||||||
|
export LIT_OPTS=-v
|
||||||
cmake --build . --target check-mlir-lit
|
cmake --build . --target check-mlir-lit
|
Loading…
Reference in New Issue