我是Spark
的新人,我必须处理巨大的时间序列。对于基准测试,我需要比较rollmean的几个实现。在numpy的迭代模式下,它非常快(1,000,000点0.055970s,窗口= 3)。我写了一个新的comer-in-pyspark版本的rollmean,结果很糟糕(同一个向量几秒钟)。
例如,我有
ts_list = ["key1", "key2",...,"keyN"]
seq = sc.parallelize(ts_list)
d = {"key1": [1, 2, 3, ...], "key2": [1, 2, 3, ...]}
我的处理:
s = seq.map(lambda s: (s, d[s]))\
.flatMap(lambda s: [(s[0], sum(elem)/k) for elem in rolling_window(np.array(s[1]), k)])\
.groupByKey().mapValues(lambda x: list(x))\
.collect()
我认为使用工人获得k分是没有价值的。我怀疑主人和工人之间的沟通是耗时的。另外我想知道我应该在并行化或内部工作者的驱动程序中加载数据吗?
如果我的矢量有数万亿分,怎么办?
答案 0 :(得分:1)
主观问题清单:
使用flatMap
后跟groupByKey
后跟mapValues
根本没有意义。它比需要的更昂贵,并且通常(不是这里)不提供关于订单的任何保证。而只需使用mapValues
来应用所需的逻辑:
def rolling_mean(xs):
...
rdd.mapValues(rolling_mean)
创建NumPy数组非常昂贵。如果这些很小,开销就会变得相当大。由于您未提供rolling_window
的实现,因此可以执行有意义的测试,但一般情况下,如果您从NumPy
开始使用sliding_window
数组而不是普通list
或者内置array
应该更快
数据加载:
我是否应该使用parallelize或在worker内部加载驱动程序中的数据?
如果可能,您应该始终在不通过驱动程序的工作人员上加载数据。后一种选择主要用于表单测试和原型设计,并在您的程序中引入严重的IO瓶颈。此外,如果数据适合单个机器的内存,分配琐碎的计算则不太可能带来任何好处。
如果您决定parallelize
聪明地做,那就说了。
sc.parallelize(d)
不需要将d
的完整副本传递给每个执行人。
最后但并非最不重要的是有现实的期望。如果任务相对便宜,那么总成本将被驱动,但其他因素,如网络IO,本地套接字通信,序列化,反序列化和一般簿记