简介
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
方法加载临时目录的文件。
|
|