巨大なテキストファイルから特定のエントリを識別し、そのエントリに対応する行を抽出するよりも優れた(より高速な)方法を探しています。ファイルの形式は次のとおりです。
>Entry1.1
#size=1688
704 1 1 1 4
979 2 2 2 0
1220 1 1 1 4
1309 1 1 1 4
1316 1 1 1 4
1372 1 1 1 4
1374 1 1 1 4
1576 1 1 1 4
>Entry2.1
#size=6251
6110 3 1.5 0 2
6129 2 2 2 2
6136 1 1 1 4
6142 3 3 3 2
6143 4 4 4 1
6150 1 1 1 4
6152 1 1 1 4
>Entry3.2
#size=1777
AND SO ON-----------
数百から数千まで変化するため、各エントリに対応する行数(上記)を減らしました。これらすべてのエントリを保持するファイルのサイズは、100MBから600MBの範囲です。また、対応する行を識別して抽出するために通常必要なエントリの数は、数百から15,000の範囲です。現在、私はREGEXを使用してエントリ名を識別し、次の'>'記号まで対応するすべての行を抽出しています。そして、プロセスを高速化するために、Python3.0の「マルチプロセッシング」パッケージを使用します。縮小されたコードは次のとおりです。
def OldMethod(entry):##Finds entry and extracts corresponding lines till next '>'
patbase = '(>*%s(?![^\n]+?\d).+?)(?=>|(?:\s*\Z))'###pattern for extraction of gene entry
found = re.findall(patbase % entry, denfile, re.DOTALL)
if found:
print ('Entry found in density file\n')
''Do processing of corresponding line''
return processed_result
def NewMethod(entry):##As suggested in this thread
name = entry[1]
block = den_dict[name]
if found:
''Do processing of correponding lines in Block''
def PPResults(module,alist):##Parallel processing
npool = Pool(int(nproc))
res = npool.map_async(module, alist)
results = (res.get())###results returned in form of a list
return results
main():
##Read Density file, split by '>' and make dictionary for key and corresponding lines
fh_in = open(density_file, 'r') ###HUGE TEXT FILE
denfile = fh_in2.read().split('>')[1:] ###read once use repeatedly
global den_dict
den_dict = {}
for ent in denfile:
ent_splt = ent.split('\n')
den_dict[ent_splt[0]] = ent_splt[2:-1]
##Use new approach with multiprocess
results = PPResults(NewMethod, a_list)###'a_list' holds entries for that proceesing needs to be done
for i in results:##Write Results from list to file
fh_out.write(i)
500GB以上と42コアのサーバーでこれを実行しますが、処理する巨大なファイルのサイズとエントリの数によっては、スクリプトに多くの時間(数時間から1日)かかります。エントリの処理は非常に基本的であるため、プロセス全体で、特定のエントリの検索にほとんどの時間がかかります。
私が達成しようとしているのは、実行時間を可能な限り短縮することです。この分析を実行するための可能な限り最速の戦略を教えてください。
結果:
'Janne Karila'の提案(下)に従い、'NewMethod'(上)を使用した後、300エントリの実行時間は120秒で、これには巨大な密度のファイルを読み取るための85秒が含まれ、'>'==35秒で分割されます。 32コア。
REGEXで「OldMethod」(上記)を使用するのに対し、300エントリの実行時間は577秒で、これには巨大な密度のファイルを読み取るための約102秒==475秒で32コアを使用して300エントリを処理します。
巨大なファイルを読み取る時間は、12秒から102秒まで変動します。理由はわかりません。結論として、新しい方法は少なくとも10〜12倍高速です。今のところまともな改善のようです。
ありがとう
AK