我正在尝试使用deephashes处理超过1.3 mil的文件(SSDEEP)http://code.google.com/p/pyssdeep
它的作用是什么。它生成Hashes(在3-6分钟内生成1.3 mil),然后相互比较以获得相似性结果。比较非常快,但只运行单个进程不会使事情完成。所以我们放入Python Multiprocessing模块来完成任务。< / p>
结果是在30分钟内完成了1.3密耳的文本文件。使用18核(Quad Xeon处理器,总计24 CPUS)
以下是每个流程的工作原理:
完成所有处理后,剩下的文件将被合并并递归地相互比较,直到没有结果为止。
问题是,当文件列表被分成较小的(5000)文件时。有些文件包含在前5000个块中但未包含在另一个组中,这使得组不完整。
如果我在没有分块的情况下运行,则完成循环需要很长时间。超过18小时,没有完成,。不知道有多久。
请建议我。
使用的模块:multiprocessing.Pool,ssdeep python
def ssdpComparer(lst, threshold):
s = ssdeep()
check_file = []
result_data = []
lst1 = lst
set_lst = set(lst)
print '>>>START'
for tup1 in lst1:
if tup1 in check_file:
continue
for tup2 in set_lst:
score = s.compare(tup1[0], tup2[0])
if score >= threshold:
result_data.append((score, tup1[2], tup2[2])) #Score, GroupID, FileID
check_file.append(tup2)
set_lst = set_lst.difference(check_file)
print """####### DONE #######"""
remain_lst = set(lst).difference(check_file)
return (result_data, remain_lst)
def parallelProcessing(tochunk_list, total_processes, threshold, source_path, mode, REMAINING_LEN = 0):
result = []
remainining = []
pooled_lst = []
pair = []
chunks_toprocess = []
print 'Total Files:', len(tochunk_list)
if mode == MODE_INTENSIVE:
chunks_toprocess = groupWithBlockID(tochunk_list) #blockID chunks
elif mode == MODE_THOROUGH:
chunks_toprocess = groupSafeLimit(tochunk_list, TOTAL_PROCESSES) #Chunks by processes
elif mode == MODE_FAST:
chunks_toprocess = groupSafeLimit(tochunk_list) #5000 chunks
print 'No. of files group to process: %d' % (len(chunks_toprocess))
pool_obj = Pool(processes = total_processes, initializer = poolInitializer, initargs = [None, threshold, source_path, mode])
pooled_lst = pool_obj.map(matchingProcess, chunks_toprocess) #chunks_toprocess
tmp_rs, tmp_rm = getResultAndRemainingLists(pooled_lst)
result += tmp_rs
remainining += tmp_rm
print 'RESULT LEN: %s, REMAINING LEN: %s, P.R.L: %s' % (len(result), len(remainining), REMAINING_LEN)
tmp_r_len = len(remainining)
if tmp_r_len != REMAINING_LEN and len(result) > 0 :
result += parallelProcessing(remainining, total_processes, threshold, source_path, mode, tmp_r_len)
else:
result += [('','', rf[2]) for rf in remainining]
return result
def getResultAndRemainingLists(pooled_lst):
g_result = []
g_remaining = []
for tup_result in pooled_lst:
tmp_result, tmp_remaining = tup_result
g_result += tmp_result
if tmp_remaining:
g_remaining += tmp_remaining
return (g_result, g_remaining)
答案 0 :(得分:0)
第一条建议:在你的情况下,不需要 check_file 作为list =&gt;将其更改为 set() - 然后应该更好(最后解释)。
如果你需要有块可能这样的程序就足够了:
def split_to_chunks(wholeFileList):
s = ssdeep()
calculated_chunks = []
for someFileId in wholeFileList:
for chunk in calculated_chunks:
if s.compare(chunk[0], someFileId) > threshold:
chunk.append(someFileId)
break
else: # important: this else is on 'for ' level
# so if there was no 'break' so someFileId is a base for new chunk:
calculated_chunks.append( [someFileId] )
return calculated_chunks
之后你可以过滤结果: groups = filter(lambda x:len(x)&gt; 1,结果) remaining = filter(lambda x:len(x)== 1,result)
注意:此算法假设块的第一个元素是“基础”。结果的好处在很大程度上取决于ssdeep的行为(我可以想象一个奇怪的问题:ssdeep有多少传递?)如果这种相似性那么应该是...
最糟糕的情况是,如果任何一对s.compare(fileId1,fileId2)的得分不满足阈值条件(那么复杂度为n ^ 2,因此在您的情况下为1.3mln * 1.3mln)。
没有简单的方法来优化这种情况。让我们想象一下情况,其中s.compare(file1,file2)总是接近0然后(据我所知),即使你知道s.compare(A,B)非常低而且s.compare(B,C)非常那么你还是不能说s.compare(A,C)=&gt;所以你需要进行n * n次操作。
另一个注意:假设你使用了太多的结构和很多列表,例如:
set_lst = set_lst.difference(check_file)
这条指令创建了新的set(),并且set_lst和check_file中的所有元素都至少被触摸过一次,因为check_file是一个列表所以没有办法优化'差异'函数而且它有复杂性:len(check_file) * log(len(set_lst))
基本上:如果这些结构正在增长(几乎是130万),那么你的计算机需要执行更多的计算。如果你使用check_file = set()而不是[](list),那么它的复杂性应该是:len(set_lst)+ len(check_file)
同样检查元素是否在python的列表(数组)中:
if tup1 in check_file:
因为 check_file 是列表 - &gt;如果tup1不在列表中,你的cpu需要将tup1与所有元素进行比较,因此复杂度为len(check_file) 如果你将check_file更改为set,那么复杂性将在log2附近(len(check_file)) 让我们看起来更直观,假设len(* check_file *)= 1mln,你需要多少比较?
set:log2(1mln)= log2(1000000)~20
list:len(check_file)= 1mln