Python - 多处理后将切片分配给稀疏矩阵

Python - Assign slices to sparse matrix after multiprocessing

我目前正在研究一种用于图像去噪的非局部方法,并被要求构建一个内核,我们称之为 w,由图像的每个像素索引。对于上下文,如果图像具有 NxM 个像素,则内核(存储为矩阵)将具有 (NxM)^4 个元素。幸运的是,矩阵是稀疏的、对称的,并且它的对角线是已知的。所以我设计了一个函数win_largo(i,l),其中iw第i行的索引,l是我要计算的元素个数,这个returns CSR 稀疏行及其转置。

我有一个 236^2 像素的图像,所以在我的例子中 l=1500 有足够的信息,我可以有效地计算前 1500 行和列。但是,还剩下 54 196 行。为了计算它们,我使用了这样的多处理模块:

import multiprocessing as mp
nm = N*M

pool    = mp.Pool(processes=15)
results = [pool.apply_async(win_largo, args=(i,1500,) ) for i in xrange(1500, nm) ]
pool.close()
pool.join()

我得到了一个非常快速的计算(几分钟),而不是需要大约 6.45 小时来计算。但是,现在我需要保存这个结果。

为此,我编写了以下循环,其中 w 再次存储为 CSR 矩阵:

j = 0
for i in xrange(1500,nm):
    w[i,i-l:i], w[i-l:i, i] = results[j].get()
    j += 1

但大约需要 6.52 小时才能完成。有没有更快的方法来做到这一点?现在看来多处理循环没用了。

我正在使用 python 2.7 和 macOS High Sierra。

我找到方法了。

首先,切片不是办法。通过测试以下内容:

%%timeit -n 2
ws  = sparse.csr_matrix((nm, nm), dtype=np.float)
for i in xrange(5925,6000):                        # 75 iterations
    ws[i,i-l:i], ws[i-l:i, i] = win_largo(i,l)

我得到了

2 loops, best of 3: 2.02 s per loop

win_largo 需要几毫秒的时间来计算。

由于切片不是分配计算对象的最佳方式,我决定利用 win_largo 返回的稀疏切片的元素。因此,我修改了函数,使其 returns 非零索引集及其对应的数据集:

%%timeit -n 5
row_ind, col_ind, datos = [], [], []

for i in xrange(5500,6000):                        # 500 iterations
    indx_w, datos_w = win_largo(i,l)
    row_ind.extend( np.repeat(i, len(indx_w)).tolist() )
    col_ind.extend( np.add(i-l, indx_w).tolist() )
    datos.extend( datos_w.tolist() )

我得到的,让我无语:

5 loops, best of 3: 2.02 s per loop

因此,整个循环耗时3分32秒完成。不到 6 小时……大约是原始时间的 0.92%。太多了。

在此之后,我能够向每个列表添加一些额外的数据,因此生成的稀疏对象将是:

ws = sparse.csr_matrix((datos, (row_ind, col_ind)), [nm, nm])

这只花了几秒钟。总的来说,我能够在 4 分钟内得到这个矩阵 :D