en_*_*ght 10 java memory-management
我试图在Java中使用非常大的方形矩阵,大约n = 1e6或更多.矩阵不是稀疏的,所以我没有看到很多方法将它们表示为2D数组,这需要n ^ 2*sizeof(int)位的内存.显然,即使添加编译器标志以用作我的机器允许的大堆,我也会遇到堆溢出错误.
我愿意为了这个问题而假设我拥有完美的计算机(无限制的RAM等),尽管实际上我在64位机器上有16 GB的RAM.似乎我的机器只是如此相关,因为我受JVM的限制而不是我的实际硬件(因为JVM不能拥有比我的物理机更多的内存).
我理解(并且引用,例如,在这里制作一个非常大的Java数组),Java阵列甚至在理论上也不能比用于索引的MAX_INT大.
我的问题是:有没有办法从JVM堆中哄骗额外的内存
据我所知,如果有,他们可能不会给我更多信息.
例如
在C中,我可以声明静态常量变量,并将它们移动到代码的数据部分,这将比堆有更多的空间,远远超过堆栈(存储的静态变量在哪里(在C/C++中)?) .
在Java中,似乎即使我将变量复制到"数据"部分,该值也会进入java中的主堆 静态分配 - 堆,堆栈和永久生成,这意味着我已成功移动一个完整的字节堆(耶!)
我的解决方案
我的"解决方案"并不是真正的解决方案.我创建了一个简单的数据结构,它使用RandomFileAccess io过程来替换对外部文件的读写的数组访问.它仍然是恒定时间访问,但我们从Java最快的操作之一转到非常非常慢的过程(尽管我们可以同时从文件中提取"缓存"行,这使得该过程非常快速).好主意?
不是我的问题
我不是问如何在java的最大数组大小之上创建一个数组.这是不可能的.这些是嵌套数组 - 单个n大小的数组很好,其中n个引起问题.
我不是问这个如何处理"java.lang.OutOfMemoryError:Java堆空间"错误(64MB堆大小).垃圾收集是不相关的 - 我甚至无法让阵列更加担心何时被删除.
我也不能使用迭代器(我认为),否则这将是一种可能性; 像矩阵乘法这样的函数需要能够直接索引
注意:Java不是在非常大的矩阵上进行操作的正确语言.我最好使用算盘.但我在这里,这是我无法控制的.
您原来的问题有一些缺失的方面;例如,我无法相信您必须使用如此大的矩阵,并且在运行之间“忘记它们”。好吧,也许你会,我不知道。
无论如何:你的用法RandomAccessFile
是,恕我直言,几乎就在那里;只是如果我是你,我会使用FileChannel.map()
. 在 Unix 系统上,它基本上是一种调用mmap(2)
. 在下面的场景中,我假设你有一个FileChannel
矩阵(我认为你明白我的意思)。
由于您使用矩阵,因此看起来矩阵中任何给定“坐标”处的值都具有相同的长度,这意味着您可以轻松计算文件中的偏移量以将给定值读取和/或写入矩阵中。当然,您不想映射该值,而是映射包含该值的窗口;使窗口足够大以便有用,并且不用担心堆空间消耗:FileChannel.map()
不消耗堆空间(保存对象簿记)。在 64 位 JVM 上,您不必担心;如果您使用的是 32 位 JVM,则必须考虑地址空间耗尽的问题。
当然,存在过期问题:您需要这个或那个映射保持活动状态多长时间。这完全取决于您的程序以及您用它做什么。但使用 aFileChannel
并绘制相关区域是正确的方法。但是,应该提醒您,映射超过 2^31 - 1 字节是不安全的;例如,选择 2^30 (1 GiB) 字节窗口;并提醒您可以将ByteBuffer
s 转换为IntBuffer
s。
编辑:一些相关链接:
归档时间: |
|
查看次数: |
570 次 |
最近记录: |