Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将多线程计算密集型作业移植到spark_Java_Apache Spark - Fatal编程技术网

Java 将多线程计算密集型作业移植到spark

Java 将多线程计算密集型作业移植到spark,java,apache-spark,Java,Apache Spark,我正在编写使用executor服务并行化任务的代码(反复思考在小数据集上完成的机器学习计算)。 我的目标是尽可能快地执行一些代码,多次执行,并将结果存储在某个地方(总执行次数至少为100万次) 逻辑如下所示(这是一个简化的示例): 最后,调用taskcompletionexecutorservice.take(),我将“Future”的结果存储在数据库中。 但这种方法并不是真正意义上的逐点缩放 这就是我现在在spark中所做的(这是一个残酷的黑客行为,但我正在寻找如何最好地构建它的建议): 在我

我正在编写使用executor服务并行化任务的代码(反复思考在小数据集上完成的机器学习计算)。 我的目标是尽可能快地执行一些代码,多次执行,并将结果存储在某个地方(总执行次数至少为100万次)

逻辑如下所示(这是一个简化的示例):

最后,调用taskcompletionexecutorservice.take(),我将“Future”的结果存储在数据库中。 但这种方法并不是真正意义上的逐点缩放

这就是我现在在spark中所做的(这是一个残酷的黑客行为,但我正在寻找如何最好地构建它的建议):

在我看来,这种方法效率很低,因为它并没有真正在最小的作业单元上进行并行化,尽管这种作业可以正常工作。此外,count并没有真正为我做任何事情,我添加它是为了触发执行。其灵感来源于计算pi示例:


那么,有没有关于如何更好地构建spark runner的建议,以便有效地使用spark executors?

因此,我们可以做一些事情,使此代码更像spark。首先,您使用的是
过滤器
计数
,但实际使用的是这两种方法的结果。foreach的函数
foreach
可能更接近您想要的


也就是说,您正在创建一个DB连接来存储结果,我们可以通过几种方法来实现这一点。一个是:如果DB确实是您想要用于存储的,那么您可以使用
foreachPartition
mapPartitionsWithIndex
为每个分区只创建一个连接,然后执行
count()
(我知道这有点难看,但是
foreachWith
从1.0.0开始就被弃用)。您也可以只做一个简单的
映射
,然后将结果保存到许多受支持的输出格式中的一种(例如saveAsSequenceFile)。

您可以尝试另一种方法,以更好地并行化它,尽管价格不菲。代码是用scala编写的,但是python有笛卡尔方法。为简单起见,我的列表包含整数

val rdd1000 = sc.parallelize(list1000)
val rdd10 = sc.parallelize(list10)
val rdd2 = sc.parallelize(list2)

rdd1000.cartesian(rdd10).cartesian(rdd2)
    .foreachPartition((tuples: Iterator[Tuple2[Tuple2[Int, Int], Int]]) => {
        dbconn =...
        for (tuple <- tuples) {
            val a = tuple._1._1
            val b = tuple._1._2
            val c = tuple._2

            val r = new Result(a, b, c, dbconn)
            dbconn.store(r)
        }
    })
val rdd1000=sc.parallelize(列表1000)
val rdd10=sc.parallelize(列表10)
val rdd2=sc.parallelize(列表2)
笛卡尔(rdd10)笛卡尔(rdd2)
.foreachPartition((元组:迭代器[Tuple2[Tuple2[Int,Int],Int]])=>{
dbconn=。。。

对于(tuple,谢谢Holden!我也将
dbconn
传递给
runner
,在那里我的实际逻辑命中数据库并在内存中(在jvm中)存储一些数据。它有一些遗留代码,我需要进行一些实质性的重构,以删除该依赖项并创建RDD,而不是从runner中点击db。好的,然后执行
mapPartitionsWithIndex
,允许您对每个分区中的所有元素重复使用dbconn可能是最好的方法。是的,刚刚尝试过它。
mapPartitionsWithIndex
说它缺少一个return语句(需要一个RDD迭代器).但是我没有什么要返回的,我怎么才能绕过它呢?啊,是的,只返回一个空迭代器。我不确定我是否错过了一些基本的东西:在这种情况下,
dbconn
init会在每次运行时发生吗?一个缺点是笛卡尔函数是一个昂贵的操作(它会导致混乱)@Holden,是的,可能是。我提到过。另一方面,我在结果rdd上打印了debugString,它显示没有洗牌。我认为这是因为所有东西都是本地的,尽管我指定spark master为本地的[8]。所以,我想说,这种方法很好,因为它使用标准API,而且总是可以查看explain。@zengr,dbconn init在整个迭代器中只发生一次。好吧,它可以工作,但我现在很好奇,为所有列表创建RDD与在列表10、列表2等上循环不同吗?spark处理任务分配是否更有效?t是如何工作的他的impl在性能方面与@Hoden的实现不同?
sparkContext.parallelize(listOfSize1000).filter(a -> {
   dbconn = new dbconn() //Cannot init it outsize parallelize since its not serializable
   for b in listofSize10:
      for c in listOfSize2:
         Result r = new runner(a, b, c. dbconn))
         dbconn.store(r)

    return true //It serves no purpose.
}).count();
val rdd1000 = sc.parallelize(list1000)
val rdd10 = sc.parallelize(list10)
val rdd2 = sc.parallelize(list2)

rdd1000.cartesian(rdd10).cartesian(rdd2)
    .foreachPartition((tuples: Iterator[Tuple2[Tuple2[Int, Int], Int]]) => {
        dbconn =...
        for (tuple <- tuples) {
            val a = tuple._1._1
            val b = tuple._1._2
            val c = tuple._2

            val r = new Result(a, b, c, dbconn)
            dbconn.store(r)
        }
    })