我目前正在研究一种用于图像去噪的非局部方法,并被要求构建一个内核,我们将其称为w
,该内核由图像的每个像素索引。对于上下文,如果图像具有NxM
个像素,则内核(存储为矩阵)将具有(NxM)^4
个元素。幸运的是,矩阵是稀疏的,对称的,并且其对角线是已知的。所以我设计了一个函数win_largo(i,l)
,其中i
是w
第i行的索引,而l
是我要计算的元素数,返回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一起使用。
答案 0 :(得分:0)
我找到了方法。
首先,切片不是方法。通过测试以下内容:
%%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
返回的稀疏切片的元素。因此,我修改了该函数,使其返回非零的索引集及其对应的数据集:
%%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