以箭头格式编写 numpy 数组的最快方法

mat*_*fux 11 python numpy pyarrow

我正在寻找numpy使用 来存储和检索数组的快速方法pyarrow。我对检索非常满意。.arrow从我的文件中提取包含 1.000.000.000 个整数的列只需不到 1 秒的时间dtype = np.uint16

\n
import pyarrow as pa\nimport numpy as np\n\ndef write(arr, name):\n    arrays = [pa.array(col) for col in arr]\n    names = [str(i) for i in range(len(arrays))]\n    batch = pa.RecordBatch.from_arrays(arrays, names=names)\n    with pa.OSFile(name, 'wb') as sink:\n        with pa.RecordBatchStreamWriter(sink, batch.schema) as writer:\n            writer.write_batch(batch)\n\ndef read(name):\n    source = pa.memory_map(name, 'r')\n    table = pa.ipc.RecordBatchStreamReader(source).read_all()\n    for i in range(table.num_columns):\n        yield table.column(str(i)).to_numpy()\n\narr = np.random.randint(65535, size=(250, 4000000), dtype=np.uint16)\n\n%%timeit -r 1 -n 1\nwrite(arr, 'test.arrow')\n>>> 25.6 s \xc2\xb1 0 ns per loop (mean \xc2\xb1 std. dev. of 1 run, 1 loop each)\n\n%%timeit -r 1 -n 1\nfor n in read('test.arrow'): n\n>>> 901 ms \xc2\xb1 0 ns per loop (mean \xc2\xb1 std. dev. of 1 run, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n

.arrow能否提高写入格式的效率?另外,我测试了np.save

\n
%%timeit -r 1 -n 1\nnp.save('test.npy', arr)\n>>> 18.5 s \xc2\xb1 0 ns per loop (mean \xc2\xb1 std. dev. of 1 run, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n

看起来速度有点快了。我们能否优化 Apache Arrow 以进一步更好地写入.arrow格式?

\n

Art*_*hur 9

性能问题可能主要是由于 IO/磁盘速度造成的。在这种情况下,你没有太多可以改进的地方。

\n

我在我的设备上进行了一些测试。我得到的数字和你的不一样。但底线是一样的,写比读慢。

\n

生成的文件为 1.9 GB(2000023184 字节):

\n
$ ls test.arrow -l\n-rw-rw-r-- 1 0x26res 0x26res 2000023184 Nov 15 10:01 test.arrow\n
Run Code Online (Sandbox Code Playgroud)\n

在下面的代码中,我生成 1.9 GB 的随机字节,并保存它们,然后与箭头所花费的时间进行比较:

\n
import secrets\n\ndata = b"\\x00" + secrets.token_bytes(2000023184)  + b"\\x00"\n\ndef write_bytes(data, name):\n    with open(name, \'wb\') as fp:\n        fp.write(data)\n\n%%timeit -r 1 -n 1 write_bytes(data, \'test.bytes\')\n>>> 2.29 s \xc2\xb1 0 ns per loop (mean \xc2\xb1 std. dev. of 1 run, 1 loop each)\n\n%%timeit -r 1 -n 1 write(arr, \'test.arrow\')\n>>> 2.52 s \xc2\xb1 0 ns per loop (mean \xc2\xb1 std. dev. of 1 run, 1 loop each)\n
Run Code Online (Sandbox Code Playgroud)\n

在我的设备上,使用 arrow 写入数据需要 2.52 秒。如果我尝试写入那么多随机字节,则需要 2.29 秒。这意味着开销或箭头大约占写入时间的 10%,因此没有太多方法可以加快速度。

\n