Java 设置火花RDD尺寸:铸造长度为10^9+;对于循环,真的是个坏主意吗?

Java 设置火花RDD尺寸:铸造长度为10^9+;对于循环,真的是个坏主意吗?,java,for-loop,casting,apache-spark,largenumber,Java,For Loop,Casting,Apache Spark,Largenumber,(编辑:看看这个问题是从哪里开始的,它真的在一个更好的地方结束了。当通过SparkContext.parallelize()设置RDD大小限制时,它最终成为Spark中RDD大小限制的一个很好的资源,与RDD的实际大小限制相比。还发现了一些关于parallelize()的参数。)在用户文档中找不到。请特别查看zero323的评论和他接受的答案。) 没有什么新鲜事,但我找不到这个问题已经被问过了。。。问题是在Java中的大型for循环中运行强制转换可能有多错误/不可取/不适当 在将Arraylis

(编辑:看看这个问题是从哪里开始的,它真的在一个更好的地方结束了。当通过SparkContext.parallelize()设置RDD大小限制时,它最终成为Spark中RDD大小限制的一个很好的资源,与RDD的实际大小限制相比。还发现了一些关于parallelize()的参数。)在用户文档中找不到。请特别查看zero323的评论和他接受的答案。)

没有什么新鲜事,但我找不到这个问题已经被问过了。。。问题是在Java中的大型for循环中运行强制转换可能有多错误/不可取/不适当

在将Arraylist传递给SparkContext.parallelize()方法之前,我想运行for循环来初始化Arraylist。我发现将未初始化的数组传递给Spark会导致空集合错误

我看过很多关于浮球和双打作为计数器的坏主意的帖子,我明白了,只是看起来这也是个坏主意?好像一定有更好的办法

numListLen目前将为10^6*10^3,在某个点上可能与10^12一样大

    List<Double> numList = new ArrayList<Double>(numListLen);
    for (long i = 0; i < numListLen; i++) {
        numList.add((double) i);
    }
List numList=newarraylist(numlisten);
对于(长i=0;i
我很想知道这段代码具体在哪里,可以改进。我是初级CS学生,所以我还没有看到所有的角度哈哈。使用隐式转换


仅作为背景,numList将被传递给Spark,告诉它运行一个模拟并使用结果创建RDD的次数,如下所示:

javarddataset=jsc.parallelize(numList,SLICES\u AKA\u PARTITIONS)

//该函数将应用于数据集的每个成员
Double count=dataSet.map(新函数(){。。。

(事实上,我很想通过Spark运行这个Arraylist创建,但似乎没有足够的时间来保证,我的i5双核上有5秒,但如果提升到10^12,那么…更长)

问题是使用双精度或浮点作为循环计数器。在您的情况下,循环计数器很长,不会遇到相同的问题

作为循环计数器的double或float的一个问题是,浮点精度将在所表示的数字序列中留下间隙。可能会到达浮点数字有效范围内的某个位置,其中加一会低于所表示数字的精度(例如,当浮点格式仅支持15位时,需要16位)。如果循环在正常执行中通过这样一个点,它将不会递增并在无限循环中继续

双倍循环计数器的另一个问题是比较两个浮点的能力。舍入意味着要成功比较变量,您需要查看范围内的值。虽然您可能会发现1.0000000==0.99999999,但您的计算机不会。因此舍入也可能使您错过循环终止条件


这两个问题都不会发生在long-as循环计数器上。所以请享受正确的操作。

尽管我不建议使用浮点值(单精度或双精度)作为循环计数器,但在您的情况下,步长不是十进制数(使用1作为步长),一切都取决于您的最大期望数与双精度表示(52位)的分数部分

尽管如此,从2^52..2^53开始的双精度数字正确地表示整数部分,但在2^53之后,不能始终达到整数部分精度

在实践中,由于循环步骤为1,如果使用
double
作为计数器并因此避免施法(从
double
double
),则在9007199254740992之前不会遇到任何问题

执行一个简单的增量测试;您将看到9007199254740995是第一个假阳性

仅供参考:对于
float
数字,您可以安全地递增到2^24=16777216(在您提供的示例中,它使用数字10000001.0f>16777216来表示问题).

并且已经讨论了与使用
双倍
作为计数器相关的问题,并指出了在循环中创建对象的问题,但在一天结束时,您根本无法分配大于
整数.MAX_值的
数组列表。除此之外,即使有231个元素,这也是一个相当大的对象和序列网络化和网络流量会给您的工作增加大量的开销

有几种方法可以处理此问题:

  • 使用
    SparkContext.range
    方法:

    range(start: Long, end: Long, 
      step: Long = 1, numSlices: Int = defaultParallelism)
    
  • 正在使用range对象初始化
    RDD
    。在PySpark中,您可以使用或(
    xrange
    ,在Python 2中),在Scala中:

    它需要驱动程序上的恒定内存和每个执行器上的恒定网络流量(您只需传输它的开始和结束)

    在Java 8中也可以用同样的方式工作,但它看起来像是
    JavaSparkContext
    还没有提供必需的构造函数。如果你有足够的勇气处理所有的单例和
    implicits
    ,你可以直接使用Scala
    Range
    ,如果没有,你可以简单地编写一个Java友好的包装器

  • 使用
    emptyRDD
    方法/少量种子初始化
    RDD
    ,并使用
    mapPartitions(WithIndex)
    /
    flatMap
    填充它。请参阅示例

    通过一点创造力,您实际上可以通过这种方式生成无限多的元素()

  • 给定您的特定用例,您还应该看一看。它提供了来自不同发行版的许多有用的生成器


我很想知道这段代码具体在哪里——对于初学者来说,您不能分配大于整数的
ArrayList
。最大值
。不太可能。
parallelize
根本不是设计的
range(start: Long, end: Long, 
  step: Long = 1, numSlices: Int = defaultParallelism)
val rdd = sc.parallelize(1L to Long.MaxValue)