我尝试使用类似于此处所述的云数据流运行一些外部共享库函数:Running external libraries with Cloud Dataflow for grid-computing workloads。
根据方法,我有几个的问题。
文章mentioned earlier中有以下段落:
如果要调用外部库,则需要手动为该库执行此步骤。方法是:
- 将代码(以及版本信息)存储在云端存储中,如果在流中运行10,000个核心,这将消除对吞吐量的任何担忧。
- 在
@beginBundle
[sic] 方法中,创建一个synchronized块以检查该文件是否在本地资源上可用。如果没有,请使用云存储客户端库将文件拉过来。
但是,使用我的Java包,我只需将库.so
文件放入src/main/resource/linux-x86-64
目录,并按以下方式调用库函数(为了简洁起见,将其剥离为最小值)< / EM>:
import com.sun.jna.Library;
import com.sun.jna.Native;
import org.apache.beam.sdk.transforms.DoFn;
import org.apache.beam.sdk.values.KV;
public class HostLookupPipeline {
public interface LookupLibrary extends Library {
String Lookup(String domain);
}
static class LookupFn extends DoFn<String, KV<String, String>> {
private static LookupLibrary lookup;
@StartBundle
public void startBundle() {
// src/main/resource/linux-x86-64/liblookup.so
lookup = Native.loadLibrary("lookup", LookupLibrary.class);
}
@ProcessElement
public void processElement(ProcessContext c) {
String domain = c.element();
String results = lookup.Lookup(domain);
if (results != null) {
c.output(KV.of(domain, results));
}
}
}
}
这种方法是否被认为是可接受的,或者从GAR下载.so
文件与从GCS下载相比效果不佳?如果没有,我应该在下载后将文件放在哪里以使其可供Cloud Dataflow工作人员访问?
我注意到调用外部库函数的转换工作速度相当慢 - 大约90个元素 - 利用15个Cloud Dataflow工作者(自动扩展,默认最大工作者)。如果我的粗略计算是正确的,它应该快两倍。我想这是因为我为每个元素调用外部库函数。
使用Java运行时是否有任何改善外部库性能的最佳实践?
答案 0 :(得分:2)
该博客文章中的指导略有不正确 - 放置初始化代码的更好的地方是@Setup
方法,而不是@StartBundle
。
@Setup
来初始化每个将要执行它的worker的每个线程中的DoFn
实例。它是重型设置代码的预定位置。它的对应部分是@Teardown
。
@StartBundle
和@FinishBundle
的粒度更精细:每个 bundle ,这是一个非常低级别的概念,我相信他们编写批次的唯一合法用途外部服务的元素:通常在@StartBundle
中,您将初始化下一批,并在@FinishBundle
中刷新它。
通常,要调试性能,请尝试向DoFn
方法添加日志记录,并查看调用所花费的毫秒数以及与预期的比较方式。如果您遇到问题,请在问题中包含Dataflow作业ID,工程师将对其进行查看。