首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >多处理时的块大矩阵点积

多处理时的块大矩阵点积
EN

Stack Overflow用户
提问于 2018-10-09 15:52:57
回答 1查看 554关注 0票数 0

我正在实现EM-GMM的一个特例。

X是形状为1000000,900时的数据矩阵,是一个数值mmap对象

Q是形状为900,900的精度矩阵,并且是ndarray

我还使用Multiprocessing库在40个内核上并行遍历200个Q矩阵,使用相同的数据矩阵(X)。

它适用于较小的尺寸,如1mil,196,1mil,400,

但是当我尝试运行1mil时,900在某个时刻抛出了一个异常:

OSError:错误号12无法分配内存

我猜这个问题是因为我有两个很大的计算,可能分配了很大的矩阵。

作为E步骤的一部分,我需要计算:

np.sum(X.dot(Q) * X, axis=1)

作为M-step的一部分,我需要计算(W是一个1mil,1个权重的向量):

(X.T * W).dot(X)

将来我将不得不在更大的数据上运行这个EM-GMM (形状为2mil,2500甚至2mil,10k)。

我可以做些什么来提高这些计算的内存效率呢?

编辑:

我注意到worker初始化使用了pickle,因此X矩阵被转换为ndarray,并且worker不共享它(这意味着所有worker的X矩阵都是复制的,并填满了我的RAM)

我有一个如何解决它的想法,如果它被修复了,我会更新。

但是如果谁有好的主意来处理它,我将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-10-10 03:20:14

事实证明,有两个不相关的问题导致了RAM的过度使用。

首先,在为多进程工作进程进行酸洗时,将从磁盘完全读取memmap对象。

这种数据复制为每个工作进程分配了6.7 of的额外RAM。

为了解决这个问题,我创建了一个共享的RawArray并将数据加载到其中,并且在每个工作线程上使用了np.frombuffer

其次,X.dot(Q)(X.T * W)都导致numpy分配了另一个X型矩阵,也就是6.7GBRAM

我从这个帖子中创建了答案的一个变体:https://stackoverflow.com/a/21096605/5572523

由于我的矩阵很小,所以我对行进行了切片:

代码语言:javascript
复制
def _block_slices(dim_size, block_size):
    count = 0
    while True:
        yield slice(count, count + block_size, 1)
        count += block_size
        if count >= dim_size:
            raise StopIteration

现在我可以遍历批量的数据(在处理weight=0时也增加了一些额外的加速)

我设置了max_elements = 2 ** 27,因为我使用的是float64,所以这会产生一个1 1GB的矩阵(如果我没有记错的话)。

所以(X.T * W).dot(X)求助于:

代码语言:javascript
复制
def weighted_outer_prod(X, W):
    n, d = X.shape

    max_rows = max(1, int(max_elements / d))
    sigma = np.zeros([d, d])
    for mm in _block_slices(n, max_rows):
        sigma += batch_weighted_outer_prod(X[mm, :], W[mm])
    return sigma

def batch_weighted_outer_prod(batch, W):
    nz = W > 0
    buff = np.empty(batch[nz].shape)
    np.multiply(batch[nz], W[nz, np.newaxis], out=buff)
    sigma = buff.T.dot(batch[nz])
    del(buff)
    return sigma

然后np.sum(X.dot(Q) * X, axis=1)转向:(别管函数名)

代码语言:javascript
复制
def calc_l_k(X, Q):
    max_rows = max(1, int(max_elements / d))
    l_k = np.empty(n)
    for mm in _block_slices(n, max_rows):
        l_k[mm] = batch_l_k(X[mm, :], Q)

    return l_k


def batch_l_k(batch, Q):
    buff = np.empty(batch.shape)
    np.dot(batch, Q, out=buff)
    np.multiply(buff, batch, out=buff)
    l_k = -0.5 * np.sum(buff, axis=1)
    del(buff)
    return l_k

现在它运行在形状为1mil,900的X上,我希望它仍然可以在更高的维度上工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52715916

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档