【问题标题】:Matrix multiplication java 1.8矩阵乘法java 1.8
【发布时间】:2014-01-23 19:08:33
【问题描述】:

您认为在 Java 1.8 中使用新的 Stream 接口可以实现稀疏矩阵运算吗?如果是,我们需要如何实现矩阵和操作。显然,我正在寻找它最终能够使用“自动”并行化。

【问题讨论】:

  • 似乎应该是可能的。你真的尝试过自己实现它吗?
  • 不,我没有,但我想在 scala 中搜索一些类似的东西。
  • 当然是一个有趣的问题(如果我有更多时间,我会试一试),但可能有一些警告(据我判断——我不是专家) : 1. 有几十种可能的稀疏矩阵表示 - 使用哪一种? 2. streaming 的概念可能不能很好地与乘法所需的严格访问模式一起使用,并且对于输入矩阵和结果矩阵都不同。 3. 稀疏 GEMM 的并行算法通常建立在对已知数量的处理器的显式并行化...
  • ... 并且依靠“未知”线程数(在流中使用)的自动并行化使得无法利用此信息。 4. 必须在primitive 流(floatdouble)上构建它,以避免FloatDouble 的(取消)装箱。 5. 性能可能很大程度上取决于缓存,也不受流的影响。 - 无论如何,我真的很想在这里看到一些方法,所以+1
  • 一旦您摆脱了帐户麻烦,也许您可​​以通过编辑在原始问题中添加新信息。例如,如果您实际上对“SparseMatrix*DenseVector”乘法更感兴趣,那就另当别论了。

标签: java matrix-multiplication java-stream


【解决方案1】:

它可以清楚地完成。对于一个简单的 SPMV(稀疏矩阵向量乘法),如下所示,稀疏矩阵以坐标COO 格式表示(最简单的稀疏格式):

class COO {
    int x, y, value;
}

public static ArrayList<Integer> spmv(List<COO> values, ArrayList<Integer> v) {
    final ArrayList<Integer> result = new ArrayList<>(Collections.nCopies(v.size(), 0));
    values.stream().forEach(
            coo -> result.set(coo.x, result.get(coo.x) + coo.value * v.get(coo.y))
    );
    return result;
}

但我真诚地建议您使用一些预编码的东西,如果您不想在接下来的 3 年中花费生命来理解稀疏矩阵运算的性能影响。 这是一个相当大的研究/优化主题,有很多因素需要考虑(就在我的脑海中):

  1. 调度/重新排序矩阵值以提高缓存性能
  2. 针对特定问题使用最佳存储格式(例如,请参阅netlib 上的这项调查)

与手工实现相比,有许多实现可以在性能上实现数量级的改进。仅举几例,请查看:

  1. Intel MKL Sparse BLAS

  2. Nvidia's cuBLAS

如果它们尚不存在,我只会为它们编写绑定,尽管像 la4j 这样的东西看起来很有希望。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2017-03-11
    • 2013-12-23
    • 2017-07-18
    相关资源
    最近更新 更多