使用 Numpy 进行大规模矩阵乘法

Posted

技术标签:

【中文标题】使用 Numpy 进行大规模矩阵乘法【英文标题】:Large scale matrix multiplication using Numpy 【发布时间】:2018-07-22 18:52:08 【问题描述】:

我面临一个问题,我需要在两个大矩阵 A [400000 x 70000]B [70000 x 1000] 之间执行矩阵乘法。这两个矩阵很密集,没有我可以利用的特殊结构。

目前我的实现是将A 划分为多个行块,例如sub_A [2000 x 70000] 和执行sub_A * B。我注意到有很多时间花在 I/O 上,即阅读 sub_A。读取矩阵大约需要 500 秒,计算大约需要 300 秒。

在这里使用 PyTables 对提高 I/O 效率有用吗?有没有图书馆可以帮助提高时间效率?

代码如下:

def sim_phe_g(geno, betas, chunk_size):
    num_indv = geno.row_count
    num_snps = geno.col_count
    num_settings = betas.shape[1]

    phe_g = np.zeros([num_indv, num_settings])
    # divide individuals into chunks
    for i in range(0, num_indv, chunk_size):
        sub_geno = geno[i : i + chunk_size, :]
        sub_geno = sub_geno.read().val
        phe_g[i : i + chunk_size, :] = np.dot(sub_geno, betas)
    return phe_g

geno 的大小为 [400000 x 70000]betas 的大小为 [70000 x 1000]geno 这是一个存储在磁盘中的大矩阵。语句sub_geno = sub_geno.read().val 会将基因型的一部分加载到内存中。而且这种说法很费时间。

另外,由于 32GB 内存大小的限制,我将大矩阵分成块。

【问题讨论】:

时间对我来说似乎很大。显示您当前的代码,看看是否可以优化。 @Daniel 我已附上我当前的代码。 假设您有足够的内存,您可以将geno 移动到 RAM 磁盘。这应该会大大减少计算的 I/O 时间。 为什么不将矩阵划分为子矩阵(而不是行)以增加所有数据的重用率,这样 comm 就不再是问题了?为什么在达到 100x100 大小之前不采用多个分而治之的关卡?如果这还不够好,请尝试使用 strassen 的乘法,它可以将每个分/治级别的数据减少 1/8。 【参考方案1】:

尝试使用 TensowFlow 进行 GPU 优化,它非常适合矩阵乘法,因为它可以让您并行化每个操作。

【讨论】:

这应该是一条评论。【参考方案2】:

如果适用,请尝试使用 tensorflow 进行大型矩阵乘法,正如您从 article 中看到的那样,在许多情况下,在大型矩阵的情况下,tensorflow 的性能要好得多。同样的原因很可能是它主要是为了有效处理大型矩阵的目的而构建的。

更多关于矩阵乘法的具体使用请参考documentation。

我在 (1000,1000) 矩阵上对其进行了乘法测试:

numpy.matmul = 60 ms ± 5.35

tensorflow.matmul = 42.5 ms ± 2.47 m

每次运行 100 次,共享均值和标准差

附注只使用了Tensorflow的cpu版本

【讨论】:

使用 CPU 版本的 Tensorflow 是否有利于此处的矩阵乘法? 如果你可以使用 GPU,使用 tensorflow 和 GPU 将大大减少计算时间。

以上是关于使用 Numpy 进行大规模矩阵乘法的主要内容,如果未能解决你的问题,请参考以下文章

numpy的矩阵乘法

numpy/pandas矩阵乘法的多线程?

numpy 和 tensorflow 中的各种乘法(点乘和矩阵乘)

numpy 和 tensorflow 中的各种乘法(点乘和矩阵乘)

矩阵乘法在numpy/matlab/数学上的不同

矩阵乘法性能 numpy 和 eigen c++