在 python 中加速大型矩阵序列化?
Speeding up large matrix serialisation in python?
在 python (2.7) 中,我试图加快将一些非常大的矩阵序列化为基于行的格式(这些在序列化时大约有 2-50 亿行)。
输出格式为<row> <col> <value>\n
,其中row和col为整数,value为浮点数,例如:
0 0 0.4
0 1 1.2
...
12521 5498 0.456
12521 5499 0.11
输入数据是 scipy.sparse.coo_matrix
,当前使用以下序列化:
from __future__ import print_function
from __future__ import unicode_literals
import itertools
# ...code to generate 'matrix' variable skipped ...
with open('outfile', 'w') as fh:
for i, j, v in itertools.izip(matrix.row, matrix.col, matrix.data):
print(b"{} {} {}".format(i, j, v), file=fh)
根据输入矩阵,这可能需要几个小时才能完成 运行,因此即使将写入时间减少 10% 也会节省大量时间。
Pandas 似乎有点快(您可能想将它应用于固定大小的块,因为它显然最终会复制数据,以避免大量内存使用)
df = pandas.DataFrame(dict(row=row, col=col, value=value),
columns=['row', 'col', 'value'],
copy=False)
df.to_csv('outfile', sep=' ', header=False, index=False)
但更快的选择是用 Cython 编写的低级转储例程。
from libc.stdio cimport fprintf, fopen, FILE, fclose
def dump_array(bytes filename, long[:] row, long[:] col, double[:] value):
cdef FILE *fh
cdef Py_ssize_t i, n
n = row.shape[0]
fh = fopen(filename, "w")
if fh == NULL:
raise RuntimeError("file open failed")
try:
with nogil:
for i in range(n):
fprintf(fh, "%ld %ld %g\n", row[i], col[i], value[i])
finally:
fclose(fh)
时间安排:
原版:5.0秒
pandas: 3.1 秒
Cython:0.9 秒
在 python (2.7) 中,我试图加快将一些非常大的矩阵序列化为基于行的格式(这些在序列化时大约有 2-50 亿行)。
输出格式为<row> <col> <value>\n
,其中row和col为整数,value为浮点数,例如:
0 0 0.4
0 1 1.2
...
12521 5498 0.456
12521 5499 0.11
输入数据是 scipy.sparse.coo_matrix
,当前使用以下序列化:
from __future__ import print_function
from __future__ import unicode_literals
import itertools
# ...code to generate 'matrix' variable skipped ...
with open('outfile', 'w') as fh:
for i, j, v in itertools.izip(matrix.row, matrix.col, matrix.data):
print(b"{} {} {}".format(i, j, v), file=fh)
根据输入矩阵,这可能需要几个小时才能完成 运行,因此即使将写入时间减少 10% 也会节省大量时间。
Pandas 似乎有点快(您可能想将它应用于固定大小的块,因为它显然最终会复制数据,以避免大量内存使用)
df = pandas.DataFrame(dict(row=row, col=col, value=value),
columns=['row', 'col', 'value'],
copy=False)
df.to_csv('outfile', sep=' ', header=False, index=False)
但更快的选择是用 Cython 编写的低级转储例程。
from libc.stdio cimport fprintf, fopen, FILE, fclose
def dump_array(bytes filename, long[:] row, long[:] col, double[:] value):
cdef FILE *fh
cdef Py_ssize_t i, n
n = row.shape[0]
fh = fopen(filename, "w")
if fh == NULL:
raise RuntimeError("file open failed")
try:
with nogil:
for i in range(n):
fprintf(fh, "%ld %ld %g\n", row[i], col[i], value[i])
finally:
fclose(fh)
时间安排:
原版:5.0秒 pandas: 3.1 秒 Cython:0.9 秒