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很新.
所以我的主要问题是如何实现最大写入速度,而另一个问题是为什么我得到这些数字?
我不知道你是否仍在关注这个问题,但我发现你的问题很有趣,所以我在 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 感兴趣,我强烈建议您阅读本文。