1. 概述

Libtorch是Pytorch的C++接口,完成了在C++中进行网络练习、网络推理的功用。

除此之外,由于Libtorch中的大部份接口都是与Pytorch一致的,所以Libtorch仍是一个很强大的张量库,有着类似Pytorch的明晰接口,这在C++中很可贵的。假设你用过C++ Tensor库,就会发现写法比较复杂,学习本钱。由于强类型的限制和通用容器类型的缺失,C++相比Python天然更复杂,库规划者由于语言运用习气,以及为了功能等因素,规划的接口一般都是高效但难用的。而Libtorch采用了与Pytorch类似的函数接口,假设你运用过Pytorch的话,运用Libtorch学习本钱很低,后边会看到详细的比如。

另一个问题是,许多Python库中基础的操作,例如numpy.einsum函数,在C++中没有合适的代替,看看这些查找你就知道了。Libtorch处理了这个问题,Pytorch中有的它都有,所以在C++中可以简略地用torch::einsum来运用einsum函数,简直是C++开发者的福音。

此外Libtorch 是支撑GPU的,主要用于模型的推理进程,但我猜想运用GPU的话,Libtorch的Tensor操作在速度上相比别的C++ Tensor 库可能有优势,详细速度需要测验对比。当然运用C++代码的话速度不是瓶颈,本身CPU代码就够快了。

Libtorch另一个优势是编译简略,只需你装置了Pytorch,Libtorch就可以直接运用,省去了复杂的装置和装备,一分钟内就能跑起来一个简略的的示例程序。

总结来说,Libtorch有以下很吸引人的特性:

  • 强大如Numpy和Pytorch的C++ Tensor库,写法优雅丝滑,并且是支撑GPU的。

  • 可以练习神经网络

  • 可以推理神经网络模型,用在C++环境的模型部署场景

  • 编译简略

由于Pytorch开发团队是以Python优先的思路来进行Pytorch的开发的,因此我感觉Libtorch的注重程度不是很高,文档和教程也比较少,官网的示例也几乎没有,因此写一个比较完善的教程是比较有意义的。

这个系列文章中,我会对Libtorch 的Tensor库和推理神经网络进程进行介绍,由于这些内容在实践关于用Libtorch来进行网络练习的部分进行跳过,由于这部分运用的场景不是许多(用Python练习网络比C++香多了)。

本篇以Mac下的操作为例,对Libtorch的装置和简略运用进行介绍,后续内容近期会更新,敬请关注。

2. Libtorch 装置

假设你已经装置过Pytorch,那么就不必额外装置Libtorch了,由于Pytorch自带了Libtorch的CMake config 文件,运用torch.utils.cmake_prefix_path语句就能打印出来,可以直接被CMake运用,编译时增加如下的选项:

-DCMAKE_PREFIX_PATH=`python -c 'import torch;print(torch.utils.cmake_prefix_path)'

假设没有装置过Pytorch,那直接去Pytorch官网下载Libtorch 压缩包,解压到本地目录即可,后边运用CMake来指向这儿的途径就行。假设解压到LIBTORCH_ROOT目录,编译时增加下面的选项:

-DCMAKE_PREFIX_PATH=<LIBTORCH_ROOT>

3. 运用CMake 编译一个简略比如

这儿写一个简略的Libtorch比如,创立一个5×5的矩阵,然后调用einsum函数来核算矩阵的迹(对角线元素的和):

// 引进Torch头文件,Tensor类在此头文件中,别的类会在别的的头文件中
#include <torch/torch.h>
#include <iostream>
int main() {
 // 运用arange构造一个一维向量,再用reshape变换到5x5的矩阵
 torch::Tensor foo = torch::arange(25).reshape({5, 5});
 // 核算矩阵的迹
 torch::Tensor bar = torch::einsum("ii", foo);
 // 输出矩阵和对应的迹
 std::cout << "==> matrix is:\n " << foo << std::endl;
 std::cout << "==> trace of it is:\n " << bar << std::endl;
}

注意reshape中需要用花括号,由于C++没有tuple类型,Python中的(5,5)需要在C++中改写为{5, 5}。除此之外,是不是跟Python代码很类似?

记得保存上面的代码为libtorch_trace.cpp,由于CMake装备中需要写文件名。

然后在同级目录编写CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)
project(libtorch_trace)
# 需要找到Libtorch
find_package(Torch REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
add_executable(${PROJECT_NAME} libtorch_trace.cpp)
target_link_libraries(${PROJECT_NAME} "${TORCH_LIBRARIES}")
# Libtorch是根据C++14来完成的
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)

然后履行下面的命令来编译:

mkdir build
cd build
# 假设是经过Pytorch
cmake -DCMAKE_PREFIX_PATH=`python -c 'import torch;print(torch.utils.cmake_prefix_path)'` ..
#下载的独自Libtorch
# cmake -DCMAKE_PREFIX_PATH=<LIBTORCH_ROOT> ..
make -j8

编译完成后运用下面的命令来履行可履行文件:

./libtorch_trace

成果如下:

==> matrix is:
 0  1  2  3  4
 5  6  7  8  9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
[ CPULongType{5,5} ]
==> trace of it is:
60
[ CPULongType{} ]

那么我们的第一个比如就完成了。

4. 参阅

  • pytorch.org/cppdocs/ins…