2017-01-01 2 views
1

Я пытаюсь сравнить два списка хешей MD5 и идентифицировать совпадения. Один из этих списков содержит около 34 000 000 хэшей, а другой может содержать до 1 000 000.Ошибка памяти памяти Python

Использование Numpy Я экспериментировал с тем, что время для сравнения сравнивается со стандартным массивом python, и разница в производительности очень впечатляет. Экспериментальные хеш-массивы данных ив используют только содержат 1,000,000 каждый, но когда я пытаюсь имитировать целевой набор данных 34,000,000, сценарий питона возвращает следующее сообщение об ошибке:

process started - [2017-01-01 11:23:18] 
Traceback (most recent call last): 
File "compare_data.py", line 30, in <module> 
compare_array_to_array() 
File "compare_data.py", line 24, in compare_array_to_array 
np_array_01 = read_sample_data_01_array() 
File "compare_data.py", line 9, in read_sample_data_01_array 
np_array_01 = np.array(sample_data_01) 
MemoryError 

Я имел взглянуть на другие посты относительно Numpy Memory Errors, но я изо всех сил пытаюсь понять, как проблема решена, поэтому заранее извиняюсь, что этот вопрос, возможно, был задан раньше.

Полный сценарий выглядит следующим образом:

from datetime import datetime 
import numpy as np 

def read_sample_data_01_array(): 
    sample_data_01 = [] 
    with open("data_set_01.txt", "r") as fi: #34,000,000 hashes 
     for line in fi: 
      sample_data_01.append(line) 
    np_array_01 = np.array(sample_data_01) 
    return(np_array_01) 


def read_sample_data_02_array(): 
    sample_data_02 = [] 
    with open("data_set_02.txt", "r") as fi: #1,000,000 hashes 
     for line in fi: 
      sample_data_02.append(line) 
    np_array_02 = np.array(sample_data_02) 
    return(np_array_02) 


def compare_array_to_array(): 
    np_array_02 = read_sample_data_02_array() 
    np_array_01 = read_sample_data_01_array() 
    ct = np.sum(np_array_01 == np_array_02) 
    print(ct) 


print("process started - [{0}]".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S')))  
compare_array_to_array() 
print("process completed - [{0}]".format(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))) 

Текущая рабочая станция, что этот код работает с является 32bit как Python, который сказал Ubuntu может увидеть 8 Гб оперативной памяти, хотя я подозреваю, что только 4 из этого адресация? Целевая рабочая станция содержит 64 ГБ оперативной памяти и является 64-битной системой, однако я хотел бы, чтобы обслужить меньшей системы

Вот пример из строк, содержащихся в наборах данных Я пытаюсь сравнить:

XDPUXSRCYCYTYEUPQMGXEDPHQTDOCLEK 
FPNXWZTALSZULLWLPCMTGTAKIGMCAMFT 
NKIOLIINPXBMUUOLYKWWBCIXCIVKWCPO 
DPLIXJCFJOKLSZUSRPPBDBAADXEHEDZL 
NGIMMXKXZHIQHTCXRPKGWYPUPJMAJAPQ 

Большое спасибо

+0

Я ответил, но теперь у меня есть сомнения. Не могли бы вы разместить образец входных файлов? –

+0

Несомненно, я написал сценарий для генерации 32-символьных строк, которые были такими же близкими, как я мог бы имитировать хэши MD5: –

ответ

0

с этой рутиной:

def read_sample_data_01_array(): 
    sample_data_01 = [] 
    with open("data_set_01.txt", "r") as fi: #34,000,000 hashes 
     for line in fi: 
      sample_data_01.append(line) 
    np_array_01 = np.array(sample_data_01) 
    return(np_array_01) 

вы создаете родной список питона, а затем вы создаете numpy массив что. В какой-то момент требуемая память примерно равна удвоенной конечной необходимой памяти, что может объяснить, что у вас закончилась нехватка памяти.

Вы можете прочитать файл непосредственно с помощью numpy.loadtxt, но я подозреваю, что он занимает такое же количество памяти, потому что он автоматически вычисляет размер данных, так вот мое решение: с помощью fromiter и указать тип данных, как "<U32" так NumPy знает, что он выделяет не более 32 байта на ячейку (так как он не может знать максимальный размер заранее из итерационного процесса, который также, почему это экономит память):

def read_sample_data_array(filepath): 
    with open(filepath) as f: 
    array = np.fromiter((line.strip() for line in f),dtype="<U32") 
    return array 

(обратите внимание на выражение генератора на слух (line.strip() for line in f) который не выделяет память в все в отличие от [line.strip() for line in f] будет.

затем:

np_array_02 = read_sample_data_array("data_set_02.txt") 
np_array_01 = read_sample_data_array("data_set_01.txt") 

Однако, это все еще занимает слишком много памяти, поэтому позвольте мне предложить не-Numpy альтернативу, используя только базовый питона:

with open("data_set_02.txt", "r") as fi: #1,000,000 hashes 
    s = {line.strip() for line in fi} 

with open("data_set_01.txt", "r") as fi: #34,000,000 hashes 
    number_of_matches = sum(1 for line in fi if line.strip() in s) 
  1. читать «малый «набор данных и поместить его в set для быстрого поиска
  2. читайте« большие »данные, заданные линейно (без потребления памяти) и совпадающие совпадения с использованием sum и условное генераторное понимание

Это должно сделать трюк и быть относительно быстрым, даже если большой набор данных еще больше. Вам просто не нужен большой набор данных, чтобы быть в памяти.

+0

Я боюсь, что ваше решение возвращает ошибку памяти: –

+0

благодаря вашему редактированию я мог бы адаптировать свое решение. Должно быть лучше по памяти. Попробуйте. –

+0

Я пробовал изменить, и теперь я получаю сообщение об ошибке: MemoryError: не может выделить память массива. Похоже, что ошибка связана с этой строкой кода: array = np.fromiter ((line.strip() для строки в f), dtype = "

Смежные вопросы