【问题标题】:Efficiently pulling an arbitrary slice from a vector有效地从向量中提取任意切片
【发布时间】:2015-12-05 21:40:56
【问题描述】:

这和我的帖子here有点关系。

我正在尝试在 Rust 中实现矩阵乘法,我认为为了有效地做到这一点,我需要能够从矩阵中获取列数据。这很困难,因为我以行优先格式存储矩阵。

我正在使用上述link 和我之前的question 中详细介绍的展开点积实现。我希望能够为这个方法提供一个矩阵的行和另一个矩阵的列。

如何有效地从矩阵中选择列数据?更一般地说:如何选择任意数据模式(如 R、matlab、numpy 等)?

我试过了:

  1. 使用跨步视图并收集迭代器 - 这似乎太慢了。
  2. 使用标准进行循环迭代,但这似乎没有被 Rust 编译器向量化。

【问题讨论】:

  • 我觉得你缺少上下文。例如,为什么不能直接使用跨步视图?你能先转置整个(子?-)矩阵,然后去重吗?什么没有被矢量化? - 也许我们可以解决这个问题。
  • LLVM 不一定会自动矢量化跨步循环,即使它可以识别一个,请参阅llvm.org/docs/Vectorizers.html#scatter-gather

标签: matrix rust


【解决方案1】:

如果您使用更聪明的 for 循环,您就会得到问题的答案。我的意思是,如果你重新排序你的 for 循环,你不必从你的矩阵中拉出一列。这样一来,您的 CPU 缓存就会保持温暖。

如果你当前的算法是这样的:

// traditional multiplication
for i in 0..a_rows {
    for j in 0..b_cols {
        for k in 0..a_cols {
            c[i][j] += a[i][k] * b[k][j];
        } 
    }
}

由于 b[k][j] 不按顺序访问您的数据,因此您会产生很多缓存未命中。

for i in 0..a_rows {
    for k in 0..a_cols {
        // Note, that j iterates over a column of B
        for j in 0..b_cols {
            c[i][j] += a[i][k] * b[k][j];
        } 
    }
}

如果您交换两个内部循环,您将依次遍历 B 的列并利用您的缓存。首先,您将访问b[k][0],然后是b[k][1],依此类推。如果一个元素是4 字节,您可以直接从缓存中访问下一个12 元素(因为64 字节是最常见的L1 缓存行大小)。传统方法并没有那么有效地使用缓存。

【讨论】:

    猜你喜欢
    • 2013-01-26
    • 2022-01-25
    • 2012-08-29
    • 2020-05-22
    • 2016-08-26
    • 2018-05-30
    • 2015-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多