2015-01-23 3 views
2

Моя проблема в том, мне нужно прочитать около 50М строк из файла в форматеБыстрое обновление матрицы с Numpy

x1 "\t" x2 "\t" .. x10 "\t" count 

, а затем вычислить матрицу А с компонентами A [J] [I] = Sum (по всем строкам) count * x_i * x_j.

Я попробовал 2 подхода, как чтение файла строка за строкой:

1) сохранить матрицу Python и обновления в течение цикла:

for j in range(size): 
    for i in range(size): 
     A[j][i] += x[j] * x[i] * count 

2) заработаете в Numpy массив, и обновление с помощью numpy.add:

numpy.add(A, count * numpy.outer(x, x)) 

что меня удивило, что второй подход был около 30% медленнее, чем первый. И оба очень медленные - около 10 минут для всего файла ...

Есть ли способ ускорить вычисление матрицы? Может быть, есть функция, которая полностью считывала данные из файла (или в больших кусках), а не по строке в строке? Какие-либо предложения?

+1

Являются ли вкладки «\ t» или являются литеральным представлением того, что находится в файле, можете ли вы прочитать весь файл в памяти? – elyase

+0

«\ t» - это вкладки, весь файл - 4.5 ГБ, так что он подходит для памяти, хотя я не знаю, может ли он ускорить вычисление ... –

+0

Вы можете отложить умножение на 'count' до конца' i', так как 'a1 * c + a2 * c + ... + an * c = (a1 + a2 + ... + an) * c' –

ответ

2

Некоторые мысли:

  • Используйте pandas.read_csv с C двигателя, чтобы прочитать файл. Это намного быстрее, чем np.genfromtxt, потому что движок оптимизирован c/Cython.
  • Вы можете прочитать весь файл в памяти, а затем выполнить вычисления. это самый простой способ, но с точки зрения эффективности ваш процессор будет в основном бездействовать, ожидая ввода. На этот раз можно было бы лучше использовать вычисления.
  • Вы можете попробовать читать и обрабатывать строки за строкой (например: с помощью модуля cvs). Хотя io по-прежнему будет узким местом, к концу вы обработаете файл. Проблема здесь в том, что у вас все еще будет некоторая потеря эффективности из-за накладных расходов Python.
  • Вероятно, наилучшей комбинацией было бы считывание фрагментов с использованием pandas.read_csv с параметрами iterator и chunk_size параметров и процессами. Бьюсь об заклад, есть оптимальный размер куска, который побьет другие методы.
0

В зависимости от того, сколько памяти у вас есть на вашем компьютере, вы пытаетесь использовать регулярное выражение для анализа значений и преобразования и нарезки numpy для применения вычислений. Если у вас закончилась нехватка памяти, рассмотрите аналогичный подход, но прочитайте файл, скажем, в 1М строках.

txt = open("C:/temp/input.dat").read() 
values = re.split("[\t|\n]", txt.strip()) 

thefloats = [ float(x) for x in values] 
mat = np.reshape(thefloats, (num_cols, num_rows)) 

for i in range(len(counts)): 
    mat[:-1,i] *= counts[-1,i] 
1

Ваша матрица симметрична, вычислите только верхнюю половину, используя ваш первый подход (55 вычислений за строку вместо 100).

Второй подход медленнее. Я не знаю, почему, но, если вы инстанцировании 50M небольшие ndarrays, вполне возможно, что это узкое место, и, возможно, с использованием одного ndarray и копирование каждой строки данных

x = np.zeros((11,)) 
for l in data.readlines(): 
    x[:] = l.split() 
    A+=np.outer(x[:-1],x[:-1])*x[-1] 

может привести к ускорению.

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