Shell ApacheSpark:增加内核数时无法提高执行时间

Shell ApacheSpark:增加内核数时无法提高执行时间,shell,apache-spark,time,pyspark,Shell,Apache Spark,Time,Pyspark,我是新手。我正在(用法语)关注这一点 其思想是调用一个名为wordcount.py(如下复制)的脚本来计算大型文本文件中的字数。 作者建议从互联网上抓取伊利亚特并将其连接一百次,形成一个名为iliad100.txt的文件: wget http://classics.mit.edu/Homer/iliad.mb.txt for i in {1..100}; do cat iliad.mb.txt >> iliad100.txt; done 当在本地计算机上使用4个内核(local[4

我是新手。我正在(用法语)关注这一点

其思想是调用一个名为
wordcount.py
(如下复制)的脚本来计算大型文本文件中的字数。 作者建议从互联网上抓取伊利亚特并将其连接一百次,形成一个名为
iliad100.txt
的文件:

wget http://classics.mit.edu/Homer/iliad.mb.txt
for i in {1..100}; do cat iliad.mb.txt >> iliad100.txt; done
当在本地计算机上使用4个内核(
local[4]
)而不是单个内核(
local[1]
)运行脚本时,它们发现执行时间减少了约30%。 但是,无论我是否跑步:

time ./spark-2.3.1-bin-hadoop2.7/bin/spark-submit --master local[1] ./wordcount/wordcount.py ./iliad100.txt

我得到的“实时”时间大致相同。更糟:有时,使用4个核获得的时间比使用单个核获得的时间稍长

我做错了什么

我使用Spark的最新版本(3.0.0.)为Hadoop 2.7预先构建,而作者使用的是2.3.1版。 运行
lscpu
显示我的计算机有8个CPU和每个插槽4个内核


下面是脚本
wordcount.py

import sys
from pyspark import SparkContext

sc = SparkContext()
lines = sc.textFile(sys.argv[1])
word_counts = lines.flatMap(lambda line: line.split(' ')) \
                   .map(lambda word: (word, 1)) \
                   .reduceByKey(lambda count1, count2: count1 + count2) \
                   .collect()

for (word, count) in word_counts:
    print(word, count)
编辑:

我发现我必须指定我用来运行程序的Python版本


PYSPARK\u PYTHON=python3./spark-3.0.0-bin-hadoop2.7/bin/spark-submit--master local[3]./wordcount.py./iliad100.txt>output.txt

我相信,这是由于将文件加载到spark中时创建的分区数量造成的

因此,无论您分配给spark作业的核心数(在--master中)是多少,并行运行的任务数都将等于分区数

检查rdd在加载文件后创建的分区数。在
local[1]
local[4]
两种情况下


使用
rdd.getNumPartitions()
查看分区数。

调用collect操作后,结果数据将发送到驱动程序节点。接下来,提到的for循环将在运行spark驱动程序的单个jvm中执行。

我认为for循环不是并行的。非常感谢您的回答,Sathiyan!运行
print(lines.getNumPartitions())
显示在将我的文件加载到Spark时创建了3个分区。我看到“实时”时间从使用
local[1]
时的19秒下降到使用
local[2]
时的14秒,使用
local[3]
时的11秒。我想知道Spark是如何选择默认的分区数的,不过……欢迎@Sheldon。决定分区数量的因素很多。但在本地,它等于核心数。
import sys
from pyspark import SparkContext

sc = SparkContext()
lines = sc.textFile(sys.argv[1])
word_counts = lines.flatMap(lambda line: line.split(' ')) \
                   .map(lambda word: (word, 1)) \
                   .reduceByKey(lambda count1, count2: count1 + count2) \
                   .collect()

for (word, count) in word_counts:
    print(word, count)