我有一个嵌套循环,给定一个长度为S
的长字符串n
和一个长度为Q
的查询m
,检查(天真地)是否{{ 1}}是Q
的子字符串,其中包含S
个不匹配项。由于外部循环的每次迭代都是独立的,因此将其并行化以加速(对吗?)是有意义的。
例如,如果max_error
,S=ATGGTC
和Q=TCCT
,那么max_err=2
就是匹配,因为Q
中的子字符串TGGT
已经S
与<=2
不匹配。但是,如果Q
,则max_err=1
中的Q
不匹配,因为S
中没有长度为4的子字符串与S
匹配P
1}}不匹配。
<=1
为了并行化,我可以使内部循环成为如下所示的函数。 (我在此函数中移动了def is_match(S,n,Q,m,max_err): # lengths; assume n>m
for i in range(0,n-m):
cnt = 0
for k in range(m):
if S[i+k]!=Q[k]: cnt += 1
if cnt>max_err: break
if cnt<=max_err: return i
return -1
)
return -1
现在,我需要并行运行外部循环,收集结果,并检查结果中是否存在非def inner_loop(S,Q,m,i):
cnt = 0
for k in range(m):
if S[i+k]!=Q[k]: cnt += 1
if cnt>max_err: break
if cnt<=max_err: return i
return -1
。我被困在这里。以下代码是正确的吗?如何收集结果?
-1
此外,只要上述任何进程返回非def is_match_parallel(S,n,Q,m,max_err):
inner_loop_1_par = inner_loop(S=S, Q=Q, m=m, i)
result = []
pool = multiprocessing.Pool()
## the following line is not probably right
result = pool.map(inner_loop_1_par, range(n-m))
for i in range(n-m):
if result[i]!=-1: return i
return -1
值,我们就完成了,我们不需要等待其余的进程。反正有吗?
答案 0 :(得分:1)
您的想法以修改过的形式发挥作用。也就是说,pool.map()
必须用更复杂的方法代替,因为您的函数需要的参数多于可迭代参数。此外,使用您的函数依赖于返回值,并且还需要在多处理中进行特殊处理。
以下解决方案使用单独调用的Process
对象实例和一个共享变量来指示给定条件是否匹配:
from multiprocessing import Process, Value
def inner_loop(flag,S,Q,m,i,max_err):
cnt = 0
if flag.value == -1:
for k in range(m):
if S[i+k]!=Q[k]:
cnt += 1
if cnt>max_err:
break
if cnt<=max_err:
flag.value = 1
def is_match_parallel(S,n,Q,m,max_err):
flag = Value('i', -1)
processes = []
for i in range(0,n-m):
p = Process(target=inner_loop, args=(flag,S,Q,m,i,max_err,))
processes.append(p)
p.start()
for p in processes: p.join()
return flag
此解决方案是用Python 2.7编写的,但在Python 3.X中实现它应该很简单。
is_match_parallel
使用特殊的多处理对象flag
初始化共享变量Value
。默认情况下,该对象应该受到保护,以防止多个线程同时访问它,以便跳过该部分程序。 flag
是整数("i"
)天气指标Q
是S
的子字符串。它被初始化为-1,因为只有找到匹配项时,剩余的多处理inner_loop
才会将其更改为1。
为i
范围内的每个n-m
启动单独的流程。请注意,对于大范围,您可能需要对此进行基准测试,并确保启动许多过程并不会减慢速度。在这种情况下,您需要将循环拆分为更大的块,这应该不是问题。
p = Process(target=inner_loop, args=(flag,S,Q,m,i,max_err,))
使用参数inner_loop
将目标函数设置为args
,包括共享变量flag
。之后,该过程开始。在循环之后,for p in processes: p.join()
导致程序在该行上等待,直到所有进程都处理完inner_loop
。
如果找到匹配项,处理inner_loop
的流程会将flag
设置为flag.value = 1
。如果不是,flag
值将保持为-1,表示找不到匹配项。完成所有流程后,is_match_parallel
会将当前flag
作为Value
对象返回(可以通过仅返回flag.value
来更改)。
在当前版本的inner_loop
中,所有进程都调用inner_loop
,但只有当flag
仍为-1时,进程才会进入函数的主体 - 带循环。这样,一旦flag
变为1,进程将仅通过该函数进行竞争并跳过耗时的部分。
您输入的示例用法是:
s = 'ATGGTC'
q = 'TCCT'
res = is_match_parallel(s, len(s), q, len(q), 2)
print res.value
res = is_match_parallel(s, len(s), q, len(q), 1)
print res.value
分别返回1和-1。