Skip to content

Commit 31607ed

Browse files
tobegit3hubbaoxinqiChen Dihaowrongtest
authored andcommitted
[RUNTIME] Implement TVMDSOOp(TensorFlow custom op) for TVM runtime (apache#4459)
* Add implementation of TVMDSOOp * feat: Update cmake script to work with c++11 and in-repo build * feat: Use libtvm as oplib dependency * fix: Add missing link dependency to libtvm * feat: Update tf tvmdso op by review comments * fix: Update with pr comments * fix: Fix lint * feat: Add test script and fix gpu shape * feat: Add test script and fix gpu shape * fix: Conditional build tftvm op for gpu * fix: Conditional build tftvm op for gpu * fix: Fix pylint of tf_op module.py * fix: Fix pylint of tf_op module.py * feat: Conditional enable gpu test for tftvm op * feat: Conditional enable gpu test for tftvm op * feat: Add tf_tvmdsoop test script as an app test * fix: Fix gpu/cpu enabled check on tvm in test script * fix: Make tf tvmdso op test script runnable with pytest * remove unused test script test_tfop_module.py * fix: Remove pushd & popd in tfdsoop test script * fix: Upgrade tftvmop use python3 to find TensorFlow * fix: Upgrade tftvmop use python3 to find TensorFlow * fix: Change target_link_options to target_link_libraries * fix: Add tftvmop build script's c++ option * fix: Add tvm library path to tf op test library path * fix: Debug ci build for tftvm dso op * fix: Fix cmake error and skip tfop test * fix: Fix typo and indentation issues * feat: Use TF list input op def * fix: Fix style and unexpected changes Co-authored-by: baoxinqi <baoxinqi@4paradigm.com> Co-authored-by: Chen Dihao <chendihao@4paradigm.com> Co-authored-by: wrongtest <wrongtest@4paradigm.com>
1 parent 6729c7a commit 31607ed

File tree

11 files changed

+728
-0
lines changed

11 files changed

+728
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ tvm_option(USE_MICRO "Build with Micro" OFF)
4242
tvm_option(INSTALL_DEV "Install compiler infrastructure" OFF)
4343
tvm_option(HIDE_PRIVATE_SYMBOLS "Compile with -fvisibility=hidden." OFF)
4444
tvm_option(USE_TF_COMPILE_FLAGS "Build with TensorFlow's compile flags." OFF)
45+
tvm_option(USE_TF_TVMDSOOP "Build with TensorFlow TVMDSOOp" OFF)
4546

4647
# 3rdparty libraries
4748
tvm_option(DLPACK_PATH "Path to DLPACK" "3rdparty/dlpack/include")
@@ -274,6 +275,7 @@ include(cmake/modules/contrib/NNPack.cmake)
274275
include(cmake/modules/contrib/TensorRT.cmake)
275276
include(cmake/modules/contrib/HybridDump.cmake)
276277
include(cmake/modules/contrib/TFLite.cmake)
278+
include(cmake/modules/contrib/TF_TVMDSOOP.cmake)
277279

278280
if(NOT MSVC)
279281
include(CheckCXXCompilerFlag)

apps/tf_tvmdsoop/CMakeLists.txt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
cmake_minimum_required(VERSION 3.2)
18+
project(tf_tvmdsoop C CXX)
19+
20+
set(TFTVM_COMPILE_FLAGS -std=c++11)
21+
set(BUILD_TVMDSOOP_ONLY ON)
22+
set(CMAKE_CURRENT_SOURCE_DIR ${TVM_ROOT})
23+
set(CMAKE_CURRENT_BINARY_DIR ${TVM_ROOT}/build)
24+
25+
include_directories(${TVM_ROOT}/3rdparty/dlpack/include/)
26+
include_directories(${TVM_ROOT}/3rdparty/dmlc-core/include/)
27+
include_directories(${TVM_ROOT}/include)
28+
29+
link_directories(${TVM_ROOT}/build)
30+
31+
include(${TVM_ROOT}/cmake/util/FindCUDA.cmake)
32+
include(${TVM_ROOT}/cmake/modules/CUDA.cmake)
33+
34+
include(${TVM_ROOT}/cmake/modules/contrib/TF_TVMDSOOP.cmake)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
# Licensed to the Apache Software Foundation (ASF) under one
3+
# or more contributor license agreements. See the NOTICE file
4+
# distributed with this work for additional information
5+
# regarding copyright ownership. The ASF licenses this file
6+
# to you under the Apache License, Version 2.0 (the
7+
# "License"); you may not use this file except in compliance
8+
# with the License. You may obtain a copy of the License at
9+
#
10+
# http://www.apache.org/licenses/LICENSE-2.0
11+
#
12+
# Unless required by applicable law or agreed to in writing,
13+
# software distributed under the License is distributed on an
14+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
# KIND, either express or implied. See the License for the
16+
# specific language governing permissions and limitations
17+
# under the License.
18+
19+
TVM_ROOT=$(cd $(dirname $0)/../..; pwd)
20+
echo "TVM_ROOT=${TVM_ROOT}"
21+
22+
export PYTHONPATH=${TVM_ROOT}/python
23+
24+
python3 -c "import tvm; print(tvm.runtime.enabled('gpu'))" | grep -e 1
25+
if [ "$?" -eq 0 ]; then
26+
echo "Build TF_TVMDSOOP with gpu support and execute tests"
27+
CMAKE_OPTIONS="-DUSE_CUDA=ON -DPython3_EXECUTABLE=python3 -DTVM_ROOT=${TVM_ROOT}"
28+
29+
mkdir -p build
30+
cd build; cmake .. ${CMAKE_OPTIONS} && make
31+
cd ..
32+
33+
LD_LIBRARY_PATH=${TVM_ROOT}/build:./build:$LD_LIBRARY_PATH python3 -m pytest -v ./tests
34+
fi
35+
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#!/usr/bin/env python
2+
3+
# Licensed to the Apache Software Foundation (ASF) under one
4+
# or more contributor license agreements. See the NOTICE file
5+
# distributed with this work for additional information
6+
# regarding copyright ownership. The ASF licenses this file
7+
# to you under the Apache License, Version 2.0 (the
8+
# "License"); you may not use this file except in compliance
9+
# with the License. You may obtain a copy of the License at
10+
#
11+
# http://www.apache.org/licenses/LICENSE-2.0
12+
#
13+
# Unless required by applicable law or agreed to in writing,
14+
# software distributed under the License is distributed on an
15+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
# KIND, either express or implied. See the License for the
17+
# specific language governing permissions and limitations
18+
# under the License.
19+
"""Test script for tf op module"""
20+
import tempfile
21+
import os
22+
import logging
23+
import tensorflow as tf
24+
import numpy as np
25+
import tvm
26+
from tvm import te
27+
from tvm.contrib import tf_op
28+
29+
30+
def test_use_tvmdso_op():
31+
"""main test function"""
32+
33+
def export_cpu_add_lib():
34+
"""create cpu add op lib"""
35+
n = te.var("n")
36+
ph_a = te.placeholder((n,), name='ph_a')
37+
ph_b = te.placeholder((n,), name='ph_b')
38+
ph_c = te.compute(ph_a.shape, lambda i: ph_a[i] + ph_b[i], name='ph_c')
39+
sched = te.create_schedule(ph_c.op)
40+
fadd_dylib = tvm.build(sched, [ph_a, ph_b, ph_c], "c", name="vector_add")
41+
lib_path = tempfile.mktemp("tvm_add_dll.so")
42+
fadd_dylib.export_library(lib_path)
43+
return lib_path
44+
45+
46+
def export_gpu_add_lib():
47+
"""create gpu add op lib"""
48+
n = te.var("n")
49+
ph_a = te.placeholder((n,), name='ph_a')
50+
ph_b = te.placeholder((n,), name='ph_b')
51+
ph_c = te.compute(ph_a.shape, lambda i: ph_a[i] + ph_b[i], name='ph_c')
52+
sched = te.create_schedule(ph_c.op)
53+
b_axis, t_axis = sched[ph_c].split(ph_c.op.axis[0], factor=64)
54+
sched[ph_c].bind(b_axis, te.thread_axis("blockIdx.x"))
55+
sched[ph_c].bind(t_axis, te.thread_axis("threadIdx.x"))
56+
fadd_dylib = tvm.build(sched, [ph_a, ph_b, ph_c], "cuda", name="vector_add")
57+
lib_path = tempfile.mktemp("tvm_add_cuda_dll.so")
58+
fadd_dylib.export_library(lib_path)
59+
return lib_path
60+
61+
62+
def test_add(session, lib_path, tf_device):
63+
"""test add lib with TensorFlow wrapper"""
64+
module = tf_op.OpModule(lib_path)
65+
66+
left = tf.placeholder("float32", shape=[4])
67+
right = tf.placeholder("float32", shape=[4])
68+
69+
feed_dict = {left: [1.0, 2.0, 3.0, 4.0], right: [5.0, 6.0, 7.0, 8.0]}
70+
expect = np.asarray([6.0, 8.0, 10.0, 12.0])
71+
72+
add1 = module.func("vector_add", output_shape=[4], output_dtype="float")
73+
add2 = module.func("vector_add", output_shape=tf.shape(left), output_dtype="float")
74+
add3 = module.func("vector_add", output_shape=[tf.shape(left)[0]], output_dtype="float")
75+
76+
with tf.device(tf_device):
77+
output1 = session.run(add1(left, right), feed_dict)
78+
np.testing.assert_equal(output1, expect)
79+
80+
output2 = session.run(add2(left, right), feed_dict)
81+
np.testing.assert_equal(output2, expect)
82+
83+
output3 = session.run(add3(left, right), feed_dict)
84+
np.testing.assert_equal(output3, expect)
85+
86+
87+
def cpu_test(session):
88+
"""test function for cpu"""
89+
cpu_lib = None
90+
try:
91+
cpu_lib = export_cpu_add_lib()
92+
test_add(session, cpu_lib, "/cpu:0")
93+
finally:
94+
if cpu_lib is not None:
95+
os.remove(cpu_lib)
96+
97+
98+
def gpu_test(session):
99+
"""test function for gpu"""
100+
gpu_lib = None
101+
try:
102+
gpu_lib = export_gpu_add_lib()
103+
test_add(session, gpu_lib, "/gpu:0")
104+
finally:
105+
if gpu_lib is not None:
106+
os.remove(gpu_lib)
107+
108+
with tf.Session() as session:
109+
if tvm.runtime.enabled("cpu"):
110+
logging.info("Test TensorFlow op on cpu kernel")
111+
cpu_test(session)
112+
if tvm.runtime.enabled("gpu"):
113+
logging.info("Test TensorFlow op on gpu kernel")
114+
gpu_test(session)
115+
116+
117+
if __name__ == "__main__":
118+
test_use_tvmdso_op()

cmake/config.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,7 @@ set(USE_TF_COMPILE_FLAGS OFF)
212212

213213
# Whether use Thrust
214214
set(USE_THRUST OFF)
215+
216+
# Whether to build the TensorFlow TVMDSOOp module
217+
set(USE_TF_TVMDSOOP OFF)
218+
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
if(NOT USE_TF_TVMDSOOP STREQUAL "OFF")
19+
find_package(Python3 COMPONENTS Interpreter)
20+
21+
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import tensorflow as tf; print(' '.join(tf.sysconfig.get_compile_flags()))"
22+
OUTPUT_VARIABLE TF_COMPILE_FLAGS_STR
23+
RESULT_VARIABLE TF_STATUS)
24+
if (NOT ${TF_STATUS} EQUAL 0)
25+
message(FATAL_ERROR "Fail to get TensorFlow compile flags")
26+
endif()
27+
28+
if(NOT USE_CUDA STREQUAL "OFF")
29+
add_definitions(-DTF_TVMDSOOP_ENABLE_GPU)
30+
endif()
31+
32+
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import tensorflow as tf; print(' '.join(tf.sysconfig.get_link_flags()))"
33+
OUTPUT_VARIABLE TF_LINK_FLAGS_STR
34+
RESULT_VARIABLE TF_STATUS)
35+
if (NOT ${TF_STATUS} EQUAL 0)
36+
message(FATAL_ERROR "Fail to get TensorFlow link flags")
37+
endif()
38+
39+
string(REGEX REPLACE "\n" " " TF_FLAGS "${TF_COMPILE_FLAGS} ${TF_LINK_FLAGS}")
40+
separate_arguments(TF_COMPILE_FLAGS UNIX_COMMAND ${TF_COMPILE_FLAGS_STR})
41+
separate_arguments(TF_LINK_FLAGS UNIX_COMMAND ${TF_LINK_FLAGS_STR})
42+
43+
44+
set(OP_LIBRARY_NAME tvm_dso_op)
45+
file(GLOB_RECURSE TFTVM_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/src/contrib/tf_op/*.cc)
46+
add_library(${OP_LIBRARY_NAME} SHARED ${TFTVM_SRCS})
47+
set_target_properties(${OP_LIBRARY_NAME} PROPERTIES PREFIX "")
48+
set(TFTVM_LINK_FLAGS -ltvm -L${CMAKE_CURRENT_BINARY_DIR})
49+
50+
if (NOT BUILD_TVMDSOOP_ONLY STREQUAL "ON")
51+
add_dependencies(${OP_LIBRARY_NAME} tvm)
52+
endif()
53+
54+
target_compile_options(${OP_LIBRARY_NAME} PUBLIC ${TFTVM_COMPILE_FLAGS} ${TF_COMPILE_FLAGS})
55+
target_link_libraries(${OP_LIBRARY_NAME} PUBLIC ${TFTVM_LINK_FLAGS} ${TF_LINK_FLAGS})
56+
57+
endif()
58+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
"""Module container of TensorFlow TVMDSO op"""
18+
from . import module
19+
20+
OpModule = module.OpModule

0 commit comments

Comments
 (0)