【问题标题】:How to tune system parameters so numpy's load() and save() achieve maximal bandwidth for AWS HDD volumes?如何调整系统参数以使 numpy 的 load() 和 save() 实现 AWS HDD 卷的最大带宽?
【发布时间】:2019-09-07 14:40:27
【问题描述】:

python2.7如何改变每个IO读写操作的大小?

我正在尝试使用 AWS EBS HDD 存储,它通过限制 IO 操作的数量和每个操作的大小来限制带宽。引用the AWS volume type specs:

** gp2/io1 based on 16 KiB I/O size, st1/sc1 based on 1 MiB I/O size

在我的机器上运行iostat -xmdtz 1,典型的输出是这样的:

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
nvme1n1           0.00     0.00 1435.00    0.00   179.12     0.00   255.64     1.77    1.22    1.22    0.00   0.69  99.60

所以看起来 python 使用的 IO 大小是 256KB。我的问题是:

如何将其更改为 1MB,以充分发挥带宽潜力 由 AWS 提供?

虽然我认为 python 中的 IO 操作大小是由一些较低级别的模块 (io?) 决定的,但代码的相关部分如下所示: x 是一个 memmapped numpy 数组,像这样加载

x = np.load("...", mmap_mode = 'r')

然后实际读取它的那部分代码就是这段代码sn-p的最后一行:

shared_x_base = multiprocessing.Array(ctypes.c_uint32, n1*k, lock=False)
shared_x = np.ctypeslib.as_array(shared_x_base)
shared_x = shared_x.reshape(n1, k)
shared_x[:] = x[:]

编辑: 对于写作,最初的大小(和带宽)激增,如下所示:

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
nvme1n1           0.00     0.00   29.00 2033.00     3.62   507.84   507.99    59.37   28.83   33.93   28.76   0.48 100.00

但后来它解决了这个问题:

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
nvme1n1           0.00     0.00 1673.00    0.00   207.12     0.00   253.55     1.78    1.06    1.06    0.00   0.59  98.80

编辑:我也试过删除 memapping,只使用 np.load 和 np.save(this answer 建议这是要走的路,无论哪种方式我都认为它会帮助弄清楚问题的根源是什么。性能更差:

Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
nvme1n1           0.00     0.00  589.00    0.00    73.62     0.00   256.00     1.88    3.19    3.19    0.00   1.68  99.20

由于我不太确定问题是否真的出在 python 的 IO 操作大小上(请参阅 Martijn Pieters 的非常有帮助的答案),我想更一般地问一下:

如何调整系统参数以使 np.load() 和 np.save() 操作(有或没有 memmapping)在 AWS 限制策略下的最大带宽下工作?

【问题讨论】:

    标签: python amazon-ec2 io bandwidth amazon-ebs


    【解决方案1】:

    您将数组作为内存映射对象打开,它在后台使用 mmap module。最终使用 mmap system call 并且无法进一步配置。

    相反,映射文件的 I/O 块大小由内核控制,但可以通过 mmap.PAGESIZE 值或在命令行上使用 getconf PAGESIZE 发现。

    您可以通过确保您正在运行的内核中的transparent hugepages support is enabled 来调整此大小。

    但是,iostat 统计信息受到内核 I/O 缓存调整参数的严重影响。来自iostat manpage

    iostat 命令生成的报告可用于更改系统配置以更好地平衡物理磁盘之间的输入/输出负载。

    您看到的第一个“爆发”是因为iostat 为您提供了系统启动时的整体系统统计数据

    iostat 命令生成的第一个报告提供有关自系统启动以来的时间的统计信息。随后的每份报告都涵盖自上次报告以来的时间。

    不要将这些数字解释为由您的 Python 代码引起的。

    如果您想调整内核 I/O 缓存,请参阅 Performance Tuning on Linux - Disk I/O,但请注意 AWS 可能已经针对网络连接存储进行了适当调整。

    【讨论】:

    • ubuntu@ip-10-140-38-8:/sortedVolume$ getconf PAGESIZE 4096 大概意思是 4096 KB?它似乎与我从iostat 得到的不一致。另外,我注意到最初写入发生在 508 的较大块(avgqu-sz 列)处,但随后又回落到 254 左右。关于如何协调这些数字的任何想法?
    • @JustMe:不,字节,所以4KB,内存页比较小。我想您在这里查看的是内核 I/O 缓存层。
    • @JustMe:我已经确认 iostat 测量内核到块设备的性能指标。如果你想调整它,调整内核,而不是 Python。
    • 感谢所有提示。我已经删除了 mem-map 依赖项(或者至少是显式的 mem-map 依赖项)。尽管iostat 报告的大小相同,但性能似乎更差(请参阅我的问题的最新编辑)。我难住了。顺便说一句,似乎所有设备(包括我正在使用的设备)都没有配置“电梯”:$ cat /sys/block/*/queue/scheduler none none ...
    • 哦,最后一件事:我包含的写作iostat 报告是在初始报告之后生成的定期“实时”报告,确实是先涨后跌。
    猜你喜欢
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 2018-05-08
    • 2019-08-17
    相关资源
    最近更新 更多