我尝试使用Spark实现并行化图像处理技术。与传统的Spark工作不同,有数百万个任务。我只想将图像分成我拥有的工人(机器)的数量,让一个工人处理一个图像补丁。所以一个图像补丁是一个任务,如果我有12个图像补丁,我有12个任务。问题是如何明确控制每个工人的任务计划。目前的情况是,如果我对图像补丁进行并行化,它们通常会向一个或两个工作人员发送几个补丁,而其他人则无法工作。我尝试设置spark的系统属性来控制 spark.cores.max 和 spark.default.parallelism 。但它似乎没有帮助。使任务尽可能单独发送给不同工作人员的唯一方法是扩大 SparkContext.parallelize - numSlices 的第二个参数。这是代码:
img = misc.imread('test_.bmp')
height, width = img.shape
divisions, patch_width, patch_height = partitionParameters(width, height, 2, 2, border=100)
spark = SparkContext(appName="Miner")
# spark.setSystemProperty('spark.cores.max','1')
spark.setSystemProperty('spark.default.parallelism','24')
broadcast_img = spark.broadcast(img)
start = datetime.now()
print "--------------------", divisions
# run spark
run = spark.parallelize(divisions, 24).cache()
print "--------------- RDD size: ", run._jrdd.splits().size()
result = run.map(lambda (x, y): crop_sub_img(broadcast_img.value, x, y, patch_width, patch_height, width, height)) \
.map(lambda ((x, y), subimg): fastSeg.process(subimg, x, y)) \
.collect()
img = cat_sub_img(result, width, height)
end = datetime.now()
print "time cost:", (end-start)
正如您所看到的,我只在分区中设置了四个补丁。 divisions是图像补丁的x和y轴的元组列表。只有我将 numSlices 设置为高值24,远远超过了我在分区中的实际任务,现在大多数工作人员都在使用。但这似乎不合理。如果我设置为4,它将把所有任务发送给只有一个工人!必须有一些方法来控制一个工人接受的任务数量。我不熟悉Spark的核心。任何人都可以帮助我,谢谢?
有人认为,对于一名工人来说,图像尺寸太小了。因此,火花将假设一个工人可以处理并将所有人送到一个。
答案 0 :(得分:1)
一台机器有多个核心。 Spark在工作者核心之间分配工作,因为它们可以并行执行工作。如果您有12台机器,每台机器有4个核心,则总共有48个核心。您应该将图像拆分为48个补丁,以便每个核心都可以执行某些操作。如果将想象分成12个补丁,那么只有12个核心可以做,而其他36个核心将被浪费。
例外情况是您的图像处理算法是否有自己的多线程。在这种情况下,您应该在机器上启动单核工作人员。工作人员每人只能获得1个任务,您可以根据需要进行多线程。如果您运行独立的Spark群集,则可以为worker设置--cores 1
。 (参见documentation。)