如何用Python实现最高写入速度?

Moh*_*rek 5 python performance profiling file

我正在编写一个可以进行高速数据采集的程序.采集卡可以以6.8 GB/s的速度运行(它在PCIe3 x8上).现在我正在尝试流式传输到RAM磁盘,以查看我可以使用Python实现的最大写入速度.

该卡将给我5-10 MB的块,然后我可以在某处写.

我写了这段代码,它将一个10MB的块写入一个二进制文件500次.我在Windows 7 64位上使用Anaconda2,我使用了Anaconda加速的探测器.

block = 'A'*10*1024*1024
filename = "R:\\test"
f = os.open(filename, os.O_CREAT| os.O_BINARY|os.O_TRUNC|os.O_WRONLY|os.O_SEQUENTIAL)

p = profiler.Profile(signatures=False)
p.enable()
start = time.clock()
for x in range(500):
    os.write(f,block)
transferTime_sec = time.clock() - start
p.disable()
p.print_stats()

print('\nwrote %f MB' % (os.stat(filename).st_size/(1024*1024)))
Run Code Online (Sandbox Code Playgroud)

我在RAM磁盘(R:\)上测试了这个,我得到了以下输出:

在此输入图像描述

所以我想,我在RAM上获得了大约2.5 GB/s的速度.这还不错,但仍远离最大RAM吞吐量,但数字是一致的.因此,低吞吐量是一个问题.

第二个问题是,当我使用PCIe SSD测试此代码时(我使用1090 MB/s顺序写入的另一个软件进行基准测试),它给出了可比较的数字.

在此输入图像描述

这让我觉得它是缓存和/或缓冲(?)所以我只是不测量实际的IO.我不确定究竟发生了什么,因为我对python很新.

所以我的主要问题是如何实现最大写入速度,而另一个问题是为什么我得到这些数字?

Tom*_*m R 1

我不知道你是否仍在关注这个问题,但我发现你的问题很有趣,所以我在 Linux 笔记本电脑上尝试了一下。

我在 python 3.5 上运行了你的代码,发现你os.O_SYNC还需要有标志以避免缓冲问题(基本上os.write在所有数据都写入磁盘之前该函数不会返回)。我也time.clock()用它来代替time.time(),这会给我更好的结果。

import os
import time
import cProfile

def ioTest():
    block = bytes('A'*10*1024*1024, 'utf-8')
    filename = 'test.bin'
    f = os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC |
                os.O_SYNC)
    start = time.time()
    for x in range(500):
        os.write(f,block)
    os.close(f)
    transferTime_sec = time.time() - start
    msg = 'Wrote {:0f}MB in {:0.03f}s'
    print(msg.format(os.stat(filename).st_size/1024/1024,
                     transferTime_sec))
cProfile.run('ioTest()')
Run Code Online (Sandbox Code Playgroud)

另外,这篇文章讨论了使用os.O_DIRECT标志,它将使用 DMA 并避免瓶颈。我必须使用 mmap 模块才能使其在我的机器上运行:

import os
import time
import cProfile
import mmap

def ioTest():
    m = mmap.mmap(-1, 10*1024*1024)
    block = bytes('A'*10*1024*1024, 'utf-8')
    m.write(block) filename = 'test.bin'
    f = os.open(filename, os.O_WRONLY | os.O_CREAT | os.O_TRUNC |
                os.O_SYNC, os.O_DIRECT)
    start = time.time()
    for x in range(500):
        os.write(f,m)
    os.close(f)
    transferTime_sec = time.time() - start
    msg = 'Wrote {:0f}MB in {:0.03f}s.'
    print(msg.format(os.stat(filename).st_size/1024/1024,
                     transferTime_sec))
cProfile.run('ioTest()')
Run Code Online (Sandbox Code Playgroud)

这使我的机器上的写入时间减少了 40%……不错。我没有使用过os.O_SEQUENTIAL,并且os.O_BINARY在我的机器上不可用。

[编辑] :我从这个站点找到了如何使用 os.O_DIRECT 标志,它很好且深入地解释了它。如果您对 Python 中的性能和直接 IO 感兴趣,我强烈建议您阅读本文。