【问题标题】:Unexpected OutOfMemoryException in ILNumericsILNumerics 中出现意外的 OutOfMemoryException
【发布时间】:2015-07-22 20:14:06
【问题描述】:

下面的 VB .net 代码给了我一个内存不足的异常。有人知道为什么吗?

Dim vArray As ILArray(Of Double) = ILMath.rand(10000000)

Using ILScope.Enter(vArray)
   For i As Integer = 1 To 100
     vArray = ILMath.add(vArray, vArray)
   Next
End Using

非常感谢。

【问题讨论】:

  • “内存泄漏”和“内存不足异常”是完全不同的东西。
  • 没有Using ILScope.Enter(vArray) 怎么样?这是否将所有数组保留在内存中直到End Using
  • rand(10000000) 尝试创建一个包含 10^14 个元素的矩阵。不知道这是不是有意的,但它几乎不会成功,不是吗?
  • 非常感谢您的回答。删除 Using ILScope.Enter(vArray) 没有帮助。 ILMath.rand(10000000) 创建一个 10^7 的向量,可以轻松放入内存。从调试中我知道第一次分配有效。前 10 次迭代也没有问题。只有在第 11 次迭代中,我才得到内存不足异常。因此,代码似乎在每次迭代中分配内存而不释放旧内存。据我了解,这称为内存泄漏。

标签: vb.net memory-management memory-leaks garbage-collection ilnumerics


【解决方案1】:

在这个玩具示例中,您可以简单地移除人工作用域,它会运行良好:

Dim vArray As ILArray(Of Double) = ILMath.rand(10000000)

For i As Integer = 1 To 100
    vArray = ILMath.add(vArray, vArray)
Next
Console.WriteLine("OK: " + vArray(0).ToString())
Console.ReadKey()

但是,在更严重的情况下,ILScope 将成为您的朋友。如ILNumerics page 所述,人工作用域可确保确定性内存管理:

作用域内创建的所有数组都会在块被释放后被释放 离开了。

否则必须依靠 GC 进行清理。而且,如您所知,这涉及大型对象的第 2 代集合——在性能方面存在所有缺点。

为了能够处理数组,需要以某种方式收集和跟踪它们。这是否符合“内存泄漏”一词的条件,这是一个哲学问题。我不会在这里讨论它。交易是:在指令指针超出范围后,这些数组得到处理:它们的内存被放入内存池并将被重用。因此,不会触发 GC。

该方案对于长时间运行的操作和大数据特别有用。目前,仅在离开范围块之后才释放数组。因此,如果您创建的算法/循环需要的内存比机器上的可用内存多,则您需要在循环期间进行清理:

    Dim vArray As ILArray(Of Double) = ILMath.rand(10000000)

    For i As Integer = 1 To 100
        Using ILScope.Enter
            vArray.a = ILMath.add(vArray, vArray)
            ' ... 
        End Using
    Next

在这里,作用域会在每次循环迭代后清理内存。这会影响循环体内分配的所有本地数组。如果我们想要一个数组值在循环迭代中存活下来,我们可以分配给它的.a 属性,如vArray.a 所示。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多