Скорость записи массива в текстовый файл - PullRequest
0 голосов
/ 17 декабря 2018

Мне нужно записать очень «высокий» массив из двух столбцов в текстовый файл, и он очень медленный.Я считаю, что если я изменю массив на более широкий, скорость записи будет намного выше.Например,

import time
import numpy as np
dataMat1 = np.random.rand(1000,1000)
dataMat2 = np.random.rand(2,500000)
dataMat3 = np.random.rand(500000,2)
start = time.perf_counter()
with open('test1.txt','w') as f:
    np.savetxt(f,dataMat1,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('test2.txt','w') as f:
    np.savetxt(f,dataMat2,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('test3.txt','w') as f:
    np.savetxt(f,dataMat3,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

При одинаковом количестве элементов в трех матрицах данных, почему последний занимает гораздо больше времени, чем два других?Есть ли способ ускорить запись "высокого" массива данных?

Ответы [ 2 ]

0 голосов
/ 17 декабря 2018

Как указал hpaulj , savetxt - это , циклически проходя по строкам X и форматируя каждую строку индивидуально:

for row in X:
    try:
        v = format % tuple(row) + newline
    except TypeError:
        raise TypeError("Mismatch between array dtype ('%s') and "
                        "format specifier ('%s')"
                        % (str(X.dtype), format))
    fh.write(v)

Я думаю, чтоОсновным тайм-киллером здесь являются все строковые интерполяционные вызовы.Если мы соберем всю интерполяцию строк в один вызов, все пойдет намного быстрее:

with open('/tmp/test4.txt','w') as f:
    fmt = ' '.join(['%g']*dataMat3.shape[1])
    fmt = '\n'.join([fmt]*dataMat3.shape[0])
    data = fmt % tuple(dataMat3.ravel())
    f.write(data)

import io
import time
import numpy as np

dataMat1 = np.random.rand(1000,1000)
dataMat2 = np.random.rand(2,500000)
dataMat3 = np.random.rand(500000,2)
start = time.perf_counter()
with open('/tmp/test1.txt','w') as f:
    np.savetxt(f,dataMat1,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('/tmp/test2.txt','w') as f:
    np.savetxt(f,dataMat2,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('/tmp/test3.txt','w') as f:
    np.savetxt(f,dataMat3,fmt='%g',delimiter=' ')
end = time.perf_counter()
print(end-start)

start = time.perf_counter()
with open('/tmp/test4.txt','w') as f:
    fmt = ' '.join(['%g']*dataMat3.shape[1])
    fmt = '\n'.join([fmt]*dataMat3.shape[0])
    data = fmt % tuple(dataMat3.ravel())        
    f.write(data)
end = time.perf_counter()
print(end-start)

report

0.1604848340011813
0.17416274400056864
0.6634929459996783
0.16207673999997496
0 голосов
/ 17 декабря 2018

Код для savetxt является Python и доступен.В основном это делает отформатированную запись для каждой строки / строки.В сущности, он имеет значение

for row in arr:
   f.write(fmt%tuple(row))

, где fmt получено из вашего fmt и формы массива, например,

'%g %g %g ...'

Таким образом, выполняется запись в файл для каждой строкимассив.Формат строки также требует некоторого времени, но он выполняется в памяти с кодом Python.

Я ожидаю, что loadtxt/genfromtxt покажет тот же шаблон времени - для чтения многих строк потребуется больше времени.

pandas имеет более быструю загрузку CSV.Я не видел никаких обсуждений о скорости записи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...