如何使用 Spark 来分配处理负载?

How to use Spark to distribute a processing load?

全部,我将需要分配一些计算(目前只是学术性的),我正计划使用 Spark 来这样做。

我现在正在进行一些测试,它们是这样的:

我有一个包含变量的大文件,并逐行对它们求和,然后输出结果。我制作了一个非 Spark 版本,如下所示:

def linesum(inputline):
    m=0
    for i in inputline:
        m=m+i
    return m

with open('numbers.txt', 'r') as f:
    reader = csv.reader(f, delimiter=';')
    testdata = [list(map(float, rec)) for rec in reader]
testdata_out=list()
print('input  : ' + str(testdata))
for i in testdata:
    testdata_out.append(linesum(i))
testdata=testdata_out[:]

print('output : ' + str(testdata_out))
print(len(testdata))
print('OK')

和 运行 在一个 600k 行的文本文件中,然后
我已经安装了一个本地 spark,运行 下面的代码:

if 'SPARK_HOME' not in os.environ:
    os.environ['SPARK_HOME'] = 'C:\spark\spark-2.0.1-bin-hadoop2.7'

conf = SparkConf().setAppName('file_read_sum').setMaster('local[4]')

sc = SparkContext(conf=conf)



from pyspark.sql import SparkSession

def linesum(inputline):
    m=0
    tmpout=list()
    tmpout=[]
    for i in inputline:
        m=m+i

    return m

with open('numbers.txt', 'r') as f:
    reader = csv.reader(f, delimiter=';')
    testdata = [list(map(float, rec)) for rec in reader]

print('input  : ' + str(testdata))
print(len(testdata))


testdata_rdd = sc.parallelize(testdata, numSlices=(len(testdata)/10000))

testdata_out = testdata_rdd.map(linesum).collect()

testdata=testdata_out[:]

print('output : ' + str(testdata_out))
print(len(testdata_out))
print('OK')

结果匹配,但第一个(没有 Spark)比第二个快得多,我还在 4 个虚拟机中进行了分布式 Spark 安装,正如预期的那样,结果更糟。

我知道有一些开销,特别是在使用 VM 时,问题是:

1) - 我的推理合理吗? Spark 是分发此类工作的合适工具吗? (目前,我只是对线条求和,但线条可能非常大,操作可能要复杂得多(想想这里的遗传编程适应性评估))

2) - 我的代码适合分发计算吗?

3) - 我怎样才能提高这个速度?

A1) 不,Spark 可能是其他任务的好工具,但不是 GP

GP 方法打开的权力背后的核心思想是过程的零灌输。它是进化的,它是过程的自我发展的候选人多样性(每个种群成员都是一个候选解决方案,具有(非常)不同的适应度( "bestness-of-fit" ))。因此,大多数处理能力在用于增加潜力以允许进化最大宽度的进化搜索的原则中是正确的,其中遗传操作调解自我实现(通过交叉、变异和架构的变化)与自我繁殖。 Spark 恰恰相反——适用于严格的、脚本化的工作流程,对任何进化行为都有零space。

进化发生器能够扫描的群体成员的多样性越丰富越好。因此,让多样性变得更广泛,忘记用于刚性和重复 RDD 演算的工具(其中 RDD 是 Spark 中的基本抽象。代表一个 不可变 ,元素的分区集合可以并行操作”。注意单词不可变。。

注意事项: 使用 VM 测试并行(潜在)加速(好吧,实际上不是 [PARALLEL] 但是 "just"-(might-be-highly)-[CONCURENT] scheduling ) 处理性能是一个非常糟糕的主意。为什么?在共享资源上消耗更多开销(在仅基于容器的部署的情况下)加上在虚拟机管理程序服务平面中消耗额外开销,接下来绝对破坏了 VM 抽象 vCPU/vCore(s) 内的所有时间缓存位置L1/L2/L3-caches,所有那些被外部O/S纵横交错的东西,都在为他在外部进程调度器上的几个CPU-CLK-ticks而战,所以这个想法确实很糟糕,非常糟糕的反模式,可能会得到一些来自云主角支持的超级教条式广告(硬核,技术上未经调整的 PR 陈词滥调 + heavy bell$ & whistle$ ),但如果针对原始硅执行。

A2) + A3) 进化系统的分布式性质在很大程度上取决于处理的性质(工作)

考虑到我们在这里是关于 GP 的,分布式执行可能最有助于生成进化加速多样性的增加宽度,而不是在天真的代码执行中。

在 GP 中非常有益的是进化概念的全局自鲁棒性——许多不协调(异步)和非常独立的处理节点通常更强大(就实现的全局 TFLOPs 水平而言)和实际报告甚至表明,失败的节点,即使是大单位(如果不是百分之几十 (!!) 的话)仍然不会破坏在自我进化种群中进行的全局搜索的最后阶段最终实现的质量。这是一个重点!如果你能正确地将这几个核心原则运用到分布式计算节点的轻量级异步集群中,并且恰好足以满足 HPC 统治,你一定会爱上 GP GP/GA-searches!


最佳下一步:

要获得一些第一手经验,请阅读 John R. KOZA 对他的 GP 分布式处理概念的评论,其中实际使用了 +99% 的问题(并且 CPU-bound 处理应该得到最大可能的加速(令人惊讶的是不是通过重新分配,因为不愿意失去单个项目的位置))。我几乎可以肯定,如果您认真对待 GP/GA,您会喜欢它并从他的开创性工作中受益。