【问题标题】:Alternative to three dimensional array替代三维数组
【发布时间】:2013-09-11 07:29:09
【问题描述】:

我的 Floyd-Warshall 算法使用三维数组。但问题是我的内存不足,当我使用超过 100 的大小时。

float[100][100][100] array= new float[100][100][100];

所以我在考虑替代方案。一种是使用二维 Float 并将它们存储在 ArrayList 中。但这根本不起作用,因为我在初始化 Float 时遇到了麻烦,它是 null 而不是 0,因此结果是错误的。我不想再次更改我的代码,因为它也非常适合并行性。 那么是否有可能使用另一种数据结构来存储值?

【问题讨论】:

  • 如果您的内存不足,那么整个事情都需要修改。事实是,在 Android 设备上,此资源是有限的(还考虑到每个维度上 100 个的三维数组)。另一件事是使用动态数组(长度不完全为 100,但如果这是您需要的,您可能需要考虑将计算移到设备之外)。您还可以粘贴到目前为止所做的事情..
  • 你真的内存不足了吗?我已经填满了你的整个数组,整个程序只需要 19 MiB RAM。问题出在哪里?
  • 100 只是一个例子,但有时我可能需要 1000x1000x1000 而那是不可能的。无论如何,我实际上是在考虑使用这个 ArrayLists,因为如果我不再需要它们,我可以删除 List 条目。这将减少内存并可以帮助我运行我的算法。但正如我提到的,它不适用于我的算法。问题是 null、0 的东西,也许还有其他不适合 Float 的东西。

标签: java android arrays arraylist


【解决方案1】:

数组是对象,因此您不仅限于使用包装器类型。你可以创建一个float[][]的数组列表。

无论如何,100x100x100 = 1000 000 个浮点数应该占用大约 4 MB 的内存。它不是什么都没有,但似乎没有不合理的大量内存。您确定问题不在其他地方吗?您是否有可能持有不再需要且可能被垃圾回收的对象?

【讨论】:

  • 怎么样?我不知道如何在 ArrayList 中使用float[][]?一直发现只能用Float[][]
  • “如何”是什么意思?你试过什么? list=new ArrayList(); list.add(new float[100][100]);
  • 好的,看来它正在工作。我的另一个问题是现在如何设置值?我可以用list.get(i)[j][k] 获取值,这意味着i 是ArrayList 的行,j 和k 是float[][] 数组的条目。但是我怎样才能设置一个值? list.set([j][j], array[i][j]) 不工作。
  • get 方法返回一个数组,因此您可以编写list.get(i)[j][k] = number,只要i 是一个有效的索引。 (如果不是,则必须将新数组添加到列表中)
【解决方案2】:

大小为 100 的 3D 立方体中的四字节浮点数将至少占用 4,000,000 字节。这是一个相当大的块。

如果您同时将它们全部放在内存中,那么无论您使用什么数据结构,它们都会占用至少这么多空间。

您可能需要考虑将它们从内存中移出,并仅在需要时将它们移入。

执行此操作的最佳方法取决于您需要对它们进行的处理类型。例如,如果您使用以下伪代码进行直接顺序处理:

for i = 0 to 99:
    for j = 0 to 99:
        for k = 0 to 99:
            loadAndDoSomethingWith (i, j, k)
flushData()

currentlyLoaded = -1
float buffer[100]

def loadAndDoSomethingWith (i, j, k):
    if i * 100 + j != currentlyLoaded:
        flushData()
        currentlyLoaded = i * 100 + j
        read buffer from file #currentlyLoaded
    doSomethingWith (buffer, k)

def flushData():
    if currentlyLoaded != -1:
        write buffer to file #currentlyLoaded

那么你可以一次只引入一个维度(100 个浮点数)。

您可以使用 多个 缓冲区执行类似的方案,以处理更复杂的情况,例如,如果您需要来自数据结构中更多位置的数据。您应该尝试将缓冲策略与您的算法相匹配,以尽可能避免颠簸。

【讨论】:

    【解决方案3】:

    恕我直言,如果您需要 100x100x100 的浮点数,您无能为力。浮点对象比原始浮点需要更多的内存,因此使用它们来减少内存消耗是没有意义的。您只能做两件事:
    1. 更改/优化您的算法,使其使用更少的数字。
    2.在AndroidManifest中使用:

    <application
        android:name="com.myApp"
        android:allowBackup="true"
        android:icon="@drawable/app_icon"
        android:label="@string/app_name"
       android:largeHeap="true"
    

    这样你就可以增加你使用的堆的大小。
    只要我的两便士。

    【讨论】:

      【解决方案4】:

      您正在尝试从 JVM 分配 4byte*100*100*100 ~ 2MB 的 连续 内存,这非常大。而是尝试创建具有三个浮点属性的对象。你可以用任何你想要的值来初始化属性。

      class Node{
      private float u =0;
      private float v =0;
      private float l =0;
      }
      

      【讨论】:

      • 每个大小为 100 的一维数组都是一个单独的对象,因此 new float[100][100][100] 分配了 10101 个单独的对象。为什么你认为它们需要连续记忆?
      • 如果 OP 需要一百万个浮点数,具有三个 float 变量的 Node 类将如何提供帮助? 1,000,000 甚至不能被 3 整除。
      • @Joni 使用数组,JVM 有义务分配连续的内存。如果我们使用数组以外的任何数据结构(即链表或对象),JVM 可以在堆上分配任何可用内存。
      • 使用对象,JVM也有义务为对象的字段分配连续的内存,就像数组一样。
      猜你喜欢
      • 1970-01-01
      • 2016-07-01
      • 2011-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-17
      • 1970-01-01
      • 2011-08-23
      相关资源
      最近更新 更多