加载--files参数和spark分发的共享库(.so)

时间:2017-08-17 16:59:37

标签: scala apache-spark java-native-interface native

我正在尝试在运行spark作业时使用外部本机库(.so文件)。首先,我使用--files参数提交文件。

在创建System.load(SparkFiles.get(libname))之后加载我正在使用SparkContext的库(以确保填充SparkFiles)。 问题是该库仅由驱动程序节点加载,并且当任务尝试访问我正在获取的本机方法时

WARN TaskSetManager: Lost task 0.0 in stage 2.0 (TID 2, 13.0.0.206, executor 0): java.lang.UnsatisfiedLinkError

对我来说唯一有用的是在运行spark应用程序之前将.so文件复制到所有工作程序,并创建一个Scala对象,该对象将在每个任务之前加载库(可以使用{{1进行优化) }})。

我尝试使用

mapPartitions

试图避免这种情况,但没有成功。

现在,因为我正在使用EMR来运行spark作业,而不是一致的集群, 我想避免在运行作业之前将文件复制到所有节点。

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

解决方案比我想象的要简单 - 我需要的是每个JVM加载一次库

基本上我需要的是使用--files添加库文件并创建一个Loader对象:

object LibraryLoader {
    lazy val load = System.load(SparkFiles.get("libname"))
}

并在每项任务(mapfilter等)之前使用它。)

例如

rdd.map { x =>
    LibraryLoader.load
    // do some stuff with x
}

懒惰将确保在填充SparkFiles之后创建对象,并且还确保每个JVM进行单一评估。