一、Github的license
1、开源软件的License,一般是授权用户使用、拷贝、修改和再发布的合法权利及应当遵守的约定,同时包含作者的免责声明和使用自担责声明。
2、使用合适的开源许可证可以给开发者/使用者避免一些不必要的麻烦事情。
3、我还是不明白我再这里写TNN的总结,会不会侵权,知道的谢谢留言。
开源软件为什么要有授权
为什么开源项目要选择License
二、如何进行模型转换
1、目前TNN仅支持CNN,支持主流的模型文件格式,包括ONNX、PyTorch、Tensorflow以及Caffe等。
2、模型转换有三种:
(1)方法一分两步:比如Caffe先通过脚本caffe2onnx,转成ONNX模型,再通过脚本onnx2tnn,转换成TNN模型。脚本位置分别在
TNN/tools/caffe2onnx/caffe2onnx.py和TNN/tools/convert2tnn/caffe_converter/caffe2tnn.py
注意的是:执行caffe2onnx.py只需补充待转换模型位置等参数即可;执行caffe2tnn.py需要先编译,具体环境搭建以及编译步骤见TNN/doc/cn/usr/onnx2tnn.md;同时wIndows系统不建议尝试。
(2)方法二一步走:手动安装依赖工具和编译工具,使用conver2tnn转换工具,其实和方法一差不多。
(3)方法三也是一步走:通过docker image的方式使用convert2tnn转换工具,重点说一下这种方式
基于Docker的模型转换方式
TNN/doc/cn/user/convert.md之Convert2tnn Docker(推荐)这里步骤和参数说的很清楚
具体终端命令如下:
docker pull turandotkay/tnn-convert
docker images
docker tag turandotkay/tnn-convert:latest tnn-convert:latest
docker rmi turandotkay/tnn-convert:latest
docker images
#convert TF
docker run --volume=$(pwd):/workspace -it tnn-convert:latest python3 ./converter.py tf2tnn \
-tp /workspace/test.pb \
-in "input0[1,32,32,3];input1[1,32,32,3]" \
-on output0 \
-v v2.0 \
-optimize \
-align \
-input_file /workspace/in.txt \
-ref_file /workspace/ref.txt
# convert onnx
docker run --volume=$(pwd):/workspace -it tnn-convert:latest python3 ./converter.py onnx2tnn \
/workspace/mobilenetv3-small-c7eb32fe.onnx \
-optimize \
-v v3.0 \
-align \
-input_file /workspace/in.txt \
-ref_file /workspace/ref.txt
# convert caffe
docker run --volume=$(pwd):/workspace -it tnn-convert:latest python3 ./converter.py caffe2tnn \
/workspace/squeezenet.prototxt \
/workspace/squeezenet.caffemodel \
-optimize \
-v v1.0 \
-align \
-input_file /workspace/in.txt \
-ref_file /workspace/ref.txt
对docker不熟悉的小伙伴可以查一下docker的常用命令,这里备注一下相关的:
#列出本地镜像
docker images
#列出本地所有镜像(含中间映像层,默认情况下,过滤掉中间映像层)
docker images -a
#列出本地镜像中REPOSITORY为ubuntu的镜像列表
docker images ubuntu
#列出所有在运行的容器信息
docker ps
#列出最近创建的5个容器信息
docker ps -n 5
#列出所有创建的容器
#docker ps -a
#使用镜像nginx:latest以交互模式启动一个容器,并在容器内执行/bin/bash命令
docker run -it nginx:latest /bin/bash
#-i:以交互模型运行容器。-t:为容器重新分配一个伪输入终端。两个通常同时使用
#--name="nginx-lb":为容器指定一个名称
# -p:指定端口映射,格式为:主机端口:容器端口
#-v/--volume:绑定一个卷,冒号前为宿主机目录,必须为绝对路径,冒号后为镜像内挂载的路径
#使用镜像nginx:lates,以后台模式启动一个容器,将容器的80端口映射到主机的80端口,主机的目录/data映射到容器的/data
#被挂载之后的容器地址将会存在挂载的挂载内容
docker run -p 80:80 -v /data:/data -d nginx:latest
#删除指定ID的容器
docker rm 6655086fbaff 67b710cbe462
下面是我执行的命令
docker run --name="model2tnn3" --volume=/data02/lhh/models/:/workspace -p 50009:22 -it tnn-convert:latest
python3 ./converter.py tf2tnn \
-tp /workspace/tfmodel/mobilenet_v1_1.0_224_frozen.pb \
-in "input0[1,224,224,3];input1[1,224,224,3]" \
-on output0 \
-v v2.0 \
-optimize \
-align \
-input_file /workspace/in.txt \
-ref_file /workspace/ref.txt
python3 ./converter.py caffe2tnn \
/workspace/caffemodel/slim-320.prototxt \
/workspace/caffemodel/slim-320.caffemodel \
-optimize \
-v v1.0 \
-align \
-input_file /workspace/in.txt \
-ref_file /workspace/ref.txt
caffemodel转换成功后得到:
三、如何在ARM Linux跨平台交叉编译TNN
1、环境要求依赖
- 提前拉取三个镜像:qemu-user-static:register,arm64v8/ubuntu:18.04,tnn-dev:20.07
- tnn-dev:20.07是开发推理程序的环境,可以在dev里面编译TNN及Demo
- arm64v8/ubunbu:18.04里面不需要配置开发环境,它是在x86架构上模拟了一个arm64的环境。
- 在tnn-dev里通过交叉编译工具生成arm64硬件架构下可以运行的程序。
(1)注册qemu解释器
docker run --rm --privileged multiarch/qemu-user-static:register --reset
这一步很简单
(2)启动arm64模拟环境
docker run -it -v /usr/bin/qemu-aarch64-static:/usr/bin/qemu-aarch64-static -v /data02/github/TNN:/workspace/TNN arm64v8/ubuntu:18.04
在这里如果报错:
"standard_init_linux.go:207:exec user process caused"permission denied"
这可能是账户对对qemu-aarch64-static文件的权限问题
解决方法:在启动模拟环境之前设置一下权限就好了,执行这条命令
chmod 777 /usr/bin/qemu-aarch64-static
(3)启动开发环境
docker run -it -p50013:22 -v /data02/github/TNN:/workspace/TNN tnn-dev:20.07
sudo apt-get install g++-aarch64-linux-gnu gcc-aarch64-linux-gnu
备注:
/data02/github/TNN为本地的TNN工程目录
同时将工程目录TNN挂载到两个容器中,就会将这两个容器连接起来。本地TNN,容器arm64v8/ubuntu:18.04挂载的TNN以及tnn-dev:20.07挂载的TNN,三处TNN其实为一处,其中一处改变,其它两处同步改变。
也就是说,在tnn-dev:20.07编译生成可执行文件后,在arm64v8/ubuntu:18.04里面执行
2、编译步骤
(1)切换到脚本目录
cd <path_to_tnn>/scripts
(2)修改配置选项
编辑build_aarch64_linux.sh
SHARED_LIB="ON" # ON表示编译动态库,OFF表示编译静态库
ARM="ON" # ON表示编译带有Arm CPU版本的库
OPENMP="ON" # ON表示打开OpenMP
OPENCL="OFF" # ON表示编译带有Arm GPU版本的库
#ARM64:
CC=aarch64-linux-gnu-gcc # 指定C编译器
CXX=aarch64-linux-gnu-g++ # 指定C++编译器
TARGET_ARCH=aarch64 # 指定指令架构
#ARM32HF:
CC=arm-linux-gnueabihf-gcc
CXX=arm-linux-gnueabihf-g++
TARGET_ARCH=arm
(3)执行编译脚本
./build_aarch64_linux.sh
四、跑通Armlinux Demo
cd /workspace/TNN/examples/armlinux
ls
(1)修改build_aarch64.sh,配置编译选项:
CC=aarch64-linux-gnu-gcc
CXX=aarch64-linux-gnu-g++
TNN_LIB_PATH=../../scripts/build_aarch64_linux/
(2)执行build_aarch64.sh
./build_aarch64.sh
(3)执行demo
编译完成后会在armlinux下生成一个build文件夹,该文件夹下会生成一个可执行文件
demo_arm_linux
./demo_arm_linux ../../../model/SqueezeNet/squeezenet_v1.1.tnnproto ../../../model/SqueezeNet/squeezenet_v1.1.tnnmodel 224 224
如果在tnn-dev中执行会报错:
bash:./demo_arm_linux:No such file or directory
这个错误原因就是环境平台不符合,即转到容器arm64v8/ubuntu:18.04里面执行。
因为这两个容器挂载了本地的同一个目录,所以TNN目录是同步更改的。
这个demo,输入是一个随机的RGB数据,输出是一个nchw float blob,例如NCHW=1x3x256x25.
在caffe中Blob相当于tensorflow的tensor,即张量,是caffe框架中数据流的基本存储单位,caffe中关于数据的运算和存储都是基于Blob进行的。
五、ArmLinux平台耗时测试
并没有执行
TNN/benchmark
文件夹下的脚本,因为这个文件夹下的benchmark_model.sh大部分还是基于Android环境
1、修改benchmark_model.sh脚本
修改原本的
/workspace/TNN/benchmark/benchmark_android/benchmark_model.sh
,修改后为:
#!/bin/bash
ABI="arm64-v8a"
STL="c++_static"
SHARED_LIB="ON"
PROFILING="OFF"
CLEAN=""
PUSH_MODEL=""
DEVICE_TYPE=""
MODEL_TYPE=TNN
USE_NCNN_MODEL=0
ARM="ON"
OPENCL="OFF"
WORK_DIR=`pwd`
BENCHMARK_MODEL_DIR=$WORK_DIR/../benchmark-model
BUILD_DIR=build
ANDROID_DIR=/data/local/tmp/tnn-benchmark
ANDROID_DATA_DIR=$ANDROID_DIR/benchmark-model
OUTPUT_LOG_FILE=benchmark_models_result.txt
LOOP_COUNT=16
WARM_UP_COUNT=8
benchmark_model_list=(
#test.tnnproto \
resnet50.tnnproto \
mobilenet_v1.tnnproto \
mobilenet_v2.tnnproto \
squeezenet_v1.0.tnnproto \
)
function usage() {
echo "usage: ./benchmark_models.sh [-32] [-c] [-b] [-f] [-d] <device-id> [-t] <CPU/GPU>"
echo "options:"
echo " -32 Build 32 bit."
echo " -c Clean up build folders."
echo " -b build targets only"
echo " -f build profiling targets "
echo " -d run with specified device"
echo " -t CPU/GPU specify the platform to run"
}
function exit_with_msg() {
echo $1
exit 1
}
function clean_build() {
echo $1 | grep "$BUILD_DIR\b" > /dev/null
if [[ "$?" != "0" ]]; then
exit_with_msg "Warnning: $1 seems not to be a BUILD folder."
fi
rm -rf $1
mkdir $1
}
function build_android_bench() {
if [ "-c" == "$CLEAN" ]; then
clean_build $BUILD_DIR
fi
mkdir -p build
cd $BUILD_DIR
cmake ../../.. \
-DCMAKE_BUILD_TYPE=Release \
-DTNN_ARM_ENABLE:BOOL=ON \
-DTNN_OPENCL_ENABLE:BOOL=OFF \
-DTNN_OPENMP_ENABLE:BOOL=ON \
-DTNN_TEST_ENABLE:BOOL=ON \
-DTNN_BENCHMARK_MODE:BOOL=ON \
-DTNN_PROFILER_ENABLE:BOOL=${PROFILING} \
-DTNN_BUILD_SHARED:BOOL=$SHARED_LIB \
-DBUILD_FOR_ANDROID_COMMAND=true
make -j4
}
function bench_android() {
build_android_bench
if [ $? != 0 ];then
exit_with_msg "build failed"
fi
if [ "" != "$BUILD_ONLY" ]; then
echo "build done!"
exit 0
fi
mkdir -p $ANDROID_DIR
if [ ${#benchmark_model_list[*]} == 0 ];then
benchmark_model_list=`ls *.tnnproto`
fi
if [ "$DEVICE_TYPE" != "GPU" ] && [ "$DEVICE_TYPE" != "CPU" ];then
DEVICE_TYPE=""
fi
if [ "ON" == $PROFILING ]; then
WARM_UP_COUNT=5
LOOP_COUNT=1
fi
echo '' >> $ANDROID_DIR/$OUTPUT_LOG_FILE
date >> $ANDROID_DIR/$OUTPUT_LOG_FILE
cat ${WORK_DIR}/$OUTPUT_LOG_FILE
}
while [ "$1" != "" ]; do
case $1 in
-32)
shift
ABI="armeabi-v7a with NEON"
;;
-c)
shift
CLEAN="-c"
;;
-b)
shift
BUILD_ONLY="-b"
;;
-f)
shift
PROFILING="ON"
;;
-d)
shift
ADB="adb -s $1"
shift
;;
-t)
shift
DEVICE_TYPE="$1"
shift
;;
-n)
shift
MODEL_TYPE=NCNN
;;
*)
usage
exit 1
esac
done
bench_android
2、全网络性能分析
执行脚本:
./benchmark_models.sh -c
编译成功后,继续执行:
cd build/test
./TNNTest -mp ../../../benchmark-model/mobilenet_v2.tnnproto -dt ARM
3、逐层性能分析
执行脚本:
./benchmark_models.sh -c -f
编译成功后,继续执行:
cd build/test
./TNNTest -mp ../../../benchmark-model/mobilenet_v2.tnnproto -dt ARM
六、下一篇ArmLinux平台耗时测试用到的源文件test.cc