【问题标题】:Java Matrix processing timeJava 矩阵处理时间
【发布时间】:2010-08-27 23:20:16
【问题描述】:

我需要所有 Guru 的简单意见!

我开发了一个程序来做一些矩阵计算。一切正常 小矩阵。但是,当我开始计算大千列行矩阵时。它 杀死速度。

我正在考虑对每一行进行处理并将结果写入文件然后释放 内存并开始处理第二行并写入文件,依此类推。

对提高速度有帮助吗?我必须做出很大的改变来实现这个改变。那是 为什么我需要你的意见。你怎么看?

谢谢

P.S:我知道 colt 和 Jama 矩阵。由于公司原因,我无法使用这些包裹 规则。


已编辑

在我的程序中,我将所有矩阵存储在二维数组中,如果矩阵很小,那很好。但是,当它有数千列和行时。然后将所有这些矩阵存储在内存中进行计算会导致性能问题。矩阵包含浮动值。对于处理,我读取了内存中的所有矩阵存储,然后开始计算。计算后我将结果写入文件。

【问题讨论】:

  • 除了别人说的,你可以在这里描述一下你的算法,看看能不能改进。很可能算法本身就是瓶颈。
  • 面对这样一个事实,即 Java 并不适用于数值计算。使用其他适合您需求的工具。

标签: java matrix sparse-matrix matrix-multiplication


【解决方案1】:

内存真的是你的瓶颈吗?因为如果不是这样,那么停止将内容写入文件总是会比替代方案慢得多。听起来您可能遇到了算法的一些限制。

或许你应该先考虑优化算法。

正如我一直对所有性能问题所说的那样 - 询问人们是一回事,但没有什么可以替代尝试!如果现实世界的表现是可衡量的,那么意见并不重要。

【讨论】:

  • 你可以说处理速度是我的瓶颈。我是这份工作的新手。我不是 Java+数学专家。我不知道如何计算是什么在吞噬我的速度。我使用了 jvisualvm,但它只显示高级图表,而不是哪个函数或类正在消耗我的速度的详细信息
【解决方案2】:

我建议在您的代码中使用分析工具和时序语句,以便在您开始进行更改之前准确找出性能问题所在。

您可能会花很长时间“修复”一些不存在问题的东西。我怀疑您建议的文件 IO 实际上会减慢您的代码速度。

如果您的代码有效地在另一个循环中嵌套了一个循环来处理每个元素,那么随着矩阵大小的增加,您会发现速度迅速下降。如果是这样,一个值得关注的领域是并行处理您的数据,让您的代码能够利用多个 CPU/内核。

考虑更有效地实现稀疏矩阵数据结构而不是多维数组(如果您现在正在使用的话)

【讨论】:

  • 感谢您的快速回答。我已经检查过了,这是导致性能问题的矩阵计算。在我的程序中,我将所有矩阵存储在二维数组中,如果矩阵很小,那很好。但是,当它有数千列和行时。然后将所有这些矩阵存储在内存中进行计算会导致性能问题。还有其他想法吗?
  • 我认为您无法推断出性能问题与内存有关。假设您有一个 5000x5000 的双精度矩阵,并且双精度在您的 JVM 上使用 8 个字节。将整个矩阵存储在内存中会消耗 200,000,000 字节,或大约 190 MB - 在现代计算机上并不多。您可以使用 jconsole 之类的工具来查看在您的 JVM 中分配了哪些内存以及何时(至关重要)运行垃圾收集。
  • 您已标记稀疏矩阵。这意味着许多元素为零。如果您将矩阵存储为二维数组并且大多数元素为零,请考虑避免存储(和处理)空元素的替代实现。也许存储每个坐标的非空元素列表可以节省大量内存并让您更快地处理。
  • 感谢您的回答:)。如果您要使用另一个 5000x5000 的多个 5000x5000 矩阵,它将消耗多少内存和 CPU? :) 我正在做乘法运算,我有 6GB RAM 和 core2du,处理它需要几个小时:(
  • Java 是严格要求吗?这听起来像是使用专用数学程序(如 Mathematica)的好主意
【解决方案3】:

您需要记住,执行 NxN 乘以 NxN 需要 2xN^3 次计算。即便如此,它也不应该花费数小时。您应该通过转置第二个矩阵(大约 30%)来获得改进,但它确实不应该花费数小时。

所以当你 2 倍 N 时,你会增加 8 倍的时间。更糟糕的是,适合您的缓存的矩阵非常快,但小于几 MB,而且它们必须来自主内存,这会使您的操作再减慢 2-5 倍。

将数据放在磁盘上确实会减慢您的计算速度,我只建议您在 martix 不适合内存时这样做,但它会使其慢 10 倍 - 100 倍,因此购买更多内存是个好主意. (在您的情况下,您的矩阵应该足够小以适合内存)

我尝试了 Jama,这是一个非常基本的库,它使用二维数组而不是一维数组,并且在 4 岁的 labtop 上花了 7 分钟。只需使用最新的硬件并将多线程缩短到一分钟以下,您应该能够获得一半的时间。

编辑:使用 Xeon X5570,Jama 在 156 秒内将两个 5000x5000 矩阵相乘。使用我编写的并行实现,将时间缩短到 27 秒。

【讨论】:

  • 嗨,彼得,非常感谢。只是为了我自己的实验。我还下载了 jama 并使用了 7000X4000 矩阵,只是为了在我的机器上执行 SVD 计算。花了一些时间并给出了堆大小错误。我只是将他们的示例与我的矩阵一起使用。如果您愿意,我可以为您提供示例,但我认为您也可以使用 jama 下载。那么问题出在哪里?我使用 jvisualvm 来查看我哪里出错了。它再次显示我的堆大小正在上升和下降,但不是我出错的地方或类。我如何才能看到哪个类、函数或语句正在消耗我的速度?
  • 运行 Matrix.random(7000,4000).svd(),内存使用量从 812 MB 开始并一直保持在那里。 Jama SVD 制作了三个与原始阵列一样大的划痕区域。我建议你给 JVM 至少 1 GB。即 -mx1g 在命令行上。
  • Profilers 通常具有方法级别的检测,即它会告诉您在一种方法中花费了多少时间。然而,由于所有工作都在一种方法中,您需要使用 System.nanoTime() 添加自己的仪器/计时。这适用于重要的工作块,但是如果您正在查看哪个表达式或数组访问花费的时间最多,您将不得不尝试删除它并查看它如何影响时间。例如用局部变量替换数组访问。
【解决方案4】:

使用 JDK 中 jvisualvm 中的分析器来确定时间花费在哪里。

我会做一些简单的实验来确定您的算法如何扩展,因为听起来您可能会使用运行时复杂度比您想象的更高的算法。如果它在 N^3 中运行(如果您想将列表与数组相乘,这很常见),那么输入大小加倍将使运行时间加倍。

【讨论】:

  • 感谢您的回答。如何查看 jvisualvm 中哪个类、函数或语句正在消耗我的速度?
猜你喜欢
  • 2012-01-30
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-10
  • 2014-04-03
相关资源
最近更新 更多