我在這裏有一個python程序,用於將DIMACS cnf格式文件轉換爲PLA格式。我正在讀取文件中的CNF子句並將它們存儲在列表中,然後對列表元素執行操作。 本程序適用於最多15,000行(子句)的較小文件,但當我嘗試在較大的文件上運行程序時,系統內存不足。我需要操作大約90,000到120,000行的文件。有人可以請建議一些更改以優化內存使用情況嗎?以下是我的程序:Python:減少大型文件讀取 - 存儲 - 操作 - 寫入程序中的RAM使用量
import sys
#Input: CNF file path
#Output: dictionary of params and clauses from cnf file
def readCNFFile(name):
lines_str = []
inputs_dict = {}
clause_list = []
with open(name, "r") as f:
for line in f.readlines():
lines_str.append(str(line))
for current in range(len(lines_str)):
li=lines_str[current].strip()
if li.startswith("c"):
pass
elif li.startswith("C"):
pass
elif li.startswith("p"):
inputs_dict['params'] = li
else:
clause_list.append(li)
inputs_dict['clauses']=clause_list
f.close()
return inputs_dict
#Input: inputs_dict["clauses"]
#Output: list of clauses split into integers
def getClauses(clause_list):
for current in range(len(clause_list)):
temp = clause_list[current].split()
clause_list[current] = temp
for current in range(len(clause_list)):
nums = [int(n) for n in clause_list[current]]
clause_list[current]= nums
return clause_list
#Input: inputs_dict["params"]
#Output: number of inputs in PLA
def getNumInputs(param_list):
param = param_list.split()
num_inputs = int(param[2])
return num_inputs
#Input: inputs_dict["params"]
#Output: number of products in PLA
def getNumProducts(param_list):
param = param_list.split()
num_prod = int(param[3])
return num_prod
#Inputs: 1. list of clauses split into integers
# 2. number of inputs in PLA
#Output: list of products for PLA file
def getPLAlist(clause_list, num_inputs):
s = "-"
temp_list_total=[]
for current in range(len(clause_list)):
temp_list = []
for index in range(1,(num_inputs+1)):
temp_list.append("-")
for index in range(len(clause_list[current])):
for i in range(1,(num_inputs+1)):
if(abs(clause_list[current][index])==i):
if(clause_list[current][index]<0):
temp_list[i-1]="1"
else:
temp_list[i-1]="0"
temp_list_total.append(temp_list)
return temp_list_total
#Inputs: 1. input CNF file path
# 2. list of products for PLA file
# 3. number of inputs in PLA
# 4. number of products in PLA
#Output: print PLA file
def printPLAfile(inputFile, PLA_list, num_inputs, num_prod):
outputfile = inputFile.split(".")[0] + "_pla2.pla"
with open(outputfile, "w") as file_out:
file_out.write(".i ")
file_out.write(str(num_inputs))
file_out.write("\n.o 1")
file_out.write("\n.p ")
file_out.write(str(num_prod))
file_out.write("\n")
for current in range(len(PLA_list)):
for index in range(len(PLA_list[current])):
file_out.write(PLA_list[current][index],)
file_out.write(" 1 \n")
file_out.write(".e")
#Get .pla file from .cnf
#input: CNF File path
def convert_CNF_2_PLA(name):
inputs = readCNFFile(name)
clause_list = getClauses(inputs['clauses'])
num_vars = getNumInputs(inputs['params'])
num_clause = getNumProducts(inputs['params'])
PLA_list = getPLAlist(clause_list, num_vars)
printPLAfile(name, PLA_list, num_vars, num_clause)
if __name__ == '__main__':
name = sys.argv[1]
convert_CNF_2_PLA(name)
從代碼中很難說清楚,但是您是否真的需要將所有行讀入內存?行之間是否存在依賴關係?或者你可以不使用迭代器來讀取行嗎?即使這意味着一次讀取文件的子句和另一次的其他東西?另外,如果實際數據不太可變,您可以查看基於\ __ slots \ __的類。或命名元組。口述是偉大的,但相當餓了。 –
當我檢查代碼時,瓶頸函數是函數getPLAlist() 讓我來解釋一下這個問題和我的代碼: 假設每行都有一個子句: 例如。 2 -4 0在7個輸入的cnf中 我需要在第2個位置打印出0位,第4個位置打印1個,其餘5個位置在該行的PLA文件中打印爲「-0-1 ---」 所以我在temp_list 中用字符串「-------」創建一個列表然後用0和1代替第二個和第四個位置,然後將temp_list附加到PLA行的列表,即temp_list_total。 任何建議,我可以改善這種方法將不勝感激。 –
是的,但沒有一個告訴我你需要一次返回整個列表。這就是@Robin Davis所說的。我曾經批量轉換數據庫導出,這會導致在500k +表格上爆炸(代碼按表格逐個運行,在崩潰之前會吸取3-4 gb)。沒有修復它,直到我意識到*行n *不依賴於之前或之後的行並開始使用** yield **。速度保持不變,ram回落到<100mb的水平。你在這個問題上拋出的任何東西都是浪費時間,恕我直言。 –