【发布时间】:2021-01-25 11:33:47
【问题描述】:
我正在尝试在不进行多处理的情况下加速以下脚本的代码(理想情况下 >4x)。在未来的步骤中,我将实现多处理,但是即使我将其拆分为 40 个内核,当前的速度也太慢了。因此,我尝试先优化代码。
import numpy as np
def loop(x,y,q,z):
matchlist = []
for ind in range(len(x)):
matchlist.append(find_match(x[ind],y[ind],q,z))
return matchlist
def find_match(x,y,q,z):
A = np.where(q == x)
B = np.where(z == y)
return np.intersect1d(A,B)
# N will finally scale up to 10^9
N = 1000
M = 300
X = np.random.randint(M, size=N)
Y = np.random.randint(M, size=N)
# Q and Z size is fixed at 120000
Q = np.random.randint(M, size=120000)
Z = np.random.randint(M, size=120000)
# convert int32 arrays to str64 arrays, to represent original data (which are strings and not numbers)
X = np.char.mod('%d', X)
Y = np.char.mod('%d', Y)
Q = np.char.mod('%d', Q)
Z = np.char.mod('%d', Z)
matchlist = loop(X,Y,Q,Z)
我有两个长度相同的数组(X 和 Y)。这些数组的每一行对应一个 DNA 测序读数(基本上是字母“A”、“C”、“G”、“T”的字符串;细节与此处的示例代码无关)。
我还有两个长度相同的“参考数组”(Q 和 Z),我想找到 Q 中 X 的每个元素以及每个元素的出现(使用 np.where()) Z 中的 Y(基本上是 find_match() 函数)。之后我想知道为 X 和 Y 找到的 索引 之间是否存在重叠/相交。
示例输出(匹配列表;X/Y 的某些行在 Q/Y 中有匹配的索引,有些则没有,例如索引 11):
到目前为止,该代码运行良好,但在 N=10^9 的最终数据集上执行需要很长时间(在此代码示例中,N=1000 以加快测试速度)。在我的笔记本电脑上执行 1000 行 X/Y 大约需要 2.29 秒:
每个find_match() 执行大约需要 2.48 毫秒,大约是最终循环的 1/1000。
第一种方法是将 (x 和 y) 以及 (q 和 z) 结合起来,然后我只需要运行一次 np.where(),但我还不能让它工作。
我尝试在 Pandas (.loc()) 中循环和查找,但这比 np.where() 慢了大约 4 倍。
该问题与 philshem (Combine several NumPy "where" statements to one to improve performance) 最近提出的问题密切相关,但是,针对此问题提供的解决方案不适用于我这里的方法。
【问题讨论】:
-
您如何在后续流程中使用
matchlist?作为指数?len?只是记录? -
基本上,具有相同数据的布尔数组(即这些索引处的
True)是否等效? -
每行的匹配索引会很好。但我也可以接受“真”(= 至少有一个匹配)或“假”(= 不匹配),如果这大大提高了速度。
标签: python numpy performance