简介
gluten以来底层的向量化计算引擎,向量化计算需要依赖操作系统的底层指令,所以这些引擎都是c++开发的。gluten通过jni方法加载和调用c++程序,这些c++都是封装成library格式的,一般在linux环境中,是以so 文件格式来存储的。
gluten加载so文件,支持两种方式。从系统目录自动加载,或者从jar包加载。选择方式由spark.gluten.loadLibFromJar配置项决定。
对于第一种系统加载方式,只需要将需要的so文件放到jvm system property java.library.path指定的路径里即可,jvm会自动从这些路径里寻找和加载对应的so文件。以ubuntu 22.04为例,java.library.path的路径为/usr/java/packages/lib/amd64\:/usr/lib/x86_64-linux-gnu/jni\:/lib/x86_64-linux-gnu\:/usr/lib/x86_64-linux-gnu\:/usr/lib/jni\:/lib\:/usr/lib
对于第二种方式,它和系统的隔离性会更好。so文件都被打包到一个jar里,gluten会从jar包寻找和动态加载。这样就不会污染java.library.path的系统目录。
动态加载
gluten从jar包动态加载so文件的流程如下:
flowchart LR
so[so文件]
so --打包 --> jar[jar包]
jar --getResource --> classloader
classloader --write --> temp_file[临时 so 文件]
temp_file -- System.load --> jvm
so文件都被打包为jar,然后被当作resource file被读取,并且写入到临时目录中.
后面再通过System.load方法,加载临时目录的so文件。
运行错误
当运行spark gluten时,会报错FileNotFoundException,显示相关的so文件找不到,我们就可以检查jar包是否存在。
如果不存在,则需要重新打包,将缺失的so文件添加进去。
|
|
源码实现
以velox向量化引擎为例,VeloxSharedlibraryLoader定义了需要加载哪些so文件的接口。它支持多种操作系统,不同操作系统需要的so文件会有差异。VeloxSharedlibraryLoader的每个子类对应着一个操作系统,以VeloxSharedlibraryLoaderUbuntu2204为例,它对应ubuntu 22.04版本的系统。
classDiagram
class VeloxSharedlibraryLoader {
<<interface>>
+ loadLib(JniLibLoader loader)
}
class VeloxSharedlibraryLoaderCentos7
class VeloxSharedlibraryLoaderCentos8
class VeloxSharedlibraryLoaderUbuntu2004
class VeloxSharedlibraryLoaderUbuntu2204
VeloxSharedlibraryLoader <|-- VeloxSharedlibraryLoaderCentos7
VeloxSharedlibraryLoader <|-- VeloxSharedlibraryLoaderCentos8
VeloxSharedlibraryLoader <|-- VeloxSharedlibraryLoaderUbuntu2004
VeloxSharedlibraryLoader <|-- VeloxSharedlibraryLoaderUbuntu2204
上述接口只是定义了要加载哪些类,负责加载的逻辑由JniLibLoader负责。使用方法如下
|
|
newTransacation创建了JniLoadTransaction事务,它记录了需要加载的so文件集合。LoadRequest表示单个so文件。
|
|
JniLoadTransaction.commit方法实现很简单,它会遍历toLoad集合,然后调用getResourceAsStream方法读取文件内容,并且复制到指定的临时目录作。最后调用System.load方法加载临时目录的文件。
|
|