繁体   English   中英

制作一个非常大的 Java 数组

[英]Making a very large Java array

我试图找到一个Pólya 猜想的反例,该猜想将在 9 亿左右。 我正在使用一种非常有效的算法,它甚至不需要任何分解(类似于埃拉托色尼筛,但信息更多。因此,需要大量整数。

该程序高效且正确,但需要一个数组,直到要检查的 xi(它检查 (2, x) 中的所有数字)。 所以,如果反例是 9 亿,我需要一个同样大的数组。 Java 不允许我超过 2000 万。 我能做些什么来获得这么大的数组吗?

您可能想要扩展 JVM 堆的最大大小。 您可以使用命令行选项来执行此操作。

我相信它是 -Xmx3600m(3600 兆字节)

Java 将允许多达 20 亿个数组条目。 是您的机器(以及您有限的内存)无法处理如此大量的数据。

Java arrays 由 int 索引,因此数组不能大于 2^31(没有无符号整数)。 因此,数组的最大大小是 2147483648,它消耗(对于普通的 int[])8589934592 字节(= 8GB)。

因此,int-index 通常不是限制,因为无论如何您都会用完 memory。

在您的算法中,您应该使用 List(或 Map)作为您的数据结构,并选择可以增长超过 2^31 的 List(或 Map)的实现。 这可能会变得很棘手,因为“通常”的实现 ArrayList(和 HashMap)在内部使用 arrays。 您将必须实现自定义数据结构; 例如,通过使用 2 级数组(列表/数组)。 当您使用它时,您还可以尝试将这些位更紧密地打包。

没有更多开销的 9 亿个 32 位整数 - 并且总会有更多开销 - 将需要 3.35 GiB 多一点。 获得这么多 memory 的唯一方法是使用 64 位 JVM(在具有至少 8 GB RAM 的机器上)或使用一些磁盘支持的缓存。

如果您不需要一次将其全部加载到 memory 中,您可以将其分割成文件并存储在磁盘上。

“不允许”是什么意思。 您可能会遇到OutOfMemoryError ,因此请使用-Xmx命令行选项添加更多 memory 。

您可以定义自己的 class 将数据存储在一个二维数组中,该数组将更接近 sqrt(n) by sqrt(n)。 然后使用索引 function 来确定数组的两个索引。 这可以根据需要扩展到更多维度。

您将遇到的主要问题是内存不足。 如果您接近此限制,您将需要重新考虑您的算法或考虑外部存储(即文件或数据库)。

如果您的算法允许:

  • 在适合 memory 的切片中计算它。

    您将不得不为每个切片重做计算,但它通常足够快。

  • 使用较小数值类型的数组,例如字节。

根据您需要访问数组的方式,您可能会发现RandomAccessFile将允许您使用大于 memory 的文件。 但是,您获得的性能在很大程度上取决于您的访问行为。

我为 Project Euler 编写了一个版本的 Eratosthenes 筛子,它一次处理大量搜索空间。 它处理前 1M 个整数(例如),但将找到的每个素数保存在一个表中。 在您遍历了到目前为止找到的所有素数之后,数组将重新初始化,并且已经找到的素数用于在查找下一个之前标记数组。

该表将素数映射到其从数组开始的“偏移量”,以进行下一次处理迭代。

这在概念上(如果不是在实现中)类似于函数式编程语言对列表执行惰性求值的方式(尽管步骤更大)。 无需预先分配所有 memory,因为您只对通过素数测试的阵列部分感兴趣。 保持非素数对您没有用处。

该方法还为以后对素数的迭代提供了记忆。 它比扫描你的稀疏筛子数据结构每次都更快。

我支持@sfossen 的想法和@Aaron Digulla。 我会 go 用于磁盘访问。 如果您的算法可以采用 List 接口而不是普通数组,则可以将 List 中的适配器写入 memory 映射文件。

使用 Tokyo Cabinet、Berkeley DB 或任何其他基于磁盘的键值存储。 它们比任何传统数据库都快,但允许您使用磁盘而不是 memory。

9亿比特你能过得去吗? (可能存储为字节数组)。

您可以尝试将其拆分为多个 arrays。

for(int x = 0; x <= 1000000; x++){
    myFirstList.add(x);
}
for(int x = 1000001; x <= 2000000; x++){
    mySecondList.add(x);
}

然后遍历它们。

for(int x: myFirstList){
    for(int y: myFirstList){
        //Remove multiples
    }
}
//repeat for second list

请改用 memory 映射文件(Java 5 NIO 包)。 或者将筛子移动到一个小的 C 库中并使用Java JNI

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM