使用多核时是不是可能超出带宽限制?

Posted

技术标签:

【中文标题】使用多核时是不是可能超出带宽限制?【英文标题】:is it possible to exceed limit of bandwidth when using multi-core?使用多核时是否可能超出带宽限制? 【发布时间】:2018-01-29 11:30:10 【问题描述】:

我正在使用 fio 基准测试工具测试带宽。 这是我的硬件规格

    每 10 核 2 个插槽 内核版本:4.8.17 英特尔 SSD 750 系列

cpu:Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.3GHZ,ssd:Intel 固态硬盘 750 系列,400GB,20nm Intel NAND 闪存 MLC。 NVMe PCIe 3.0*4 附加卡。

当我创建 fio 文件时,我可以在启动 I/O 之前使文件的缓冲区/页面缓存部分无效。

我使用 O_DIRECT 标志(非缓冲 IO)绕过页面缓存并使用 linux 原生异步 I/O 请求。

当我使用一个核心进行测试时,fio 输出表明 core0 接收到的带宽为 1516.7MB/s。

不超过intel SSD 750的带宽限制。没关系。

这里是 test1 代码。

[global]
filename=/dev/nvme0n1
runtime=10
bs=4k
ioengine=libaio
direct=1
iodepth=64
invalidate=1 
randrepeat=0
log_avg_msec=1000
time_based
thread=1
size=256m


[job1]
cpus_allowed=0
rw=randread

但是,当我使用 3 个内核执行此操作时,内核的总带宽超过了 英特尔 SSD 750 带宽限制。

3核总带宽约为3000MB/s。

根据英特尔 SSD 750 规范,我的英特尔 SSD 带宽限制为 2200MB/s。

这里是test2(3核)的代码

[global]
filename=/dev/nvme0n1
runtime=10
bs=4k
ioengine=libaio
direct=1
iodepth=64

invalidate=1 
randrepeat=0
log_avg_msec=1000
time_based
thread=1
size=256m


[job1]
cpus_allowed=0
rw=randread

[job2]
cpus_allowed=1
rw=randread

[job3]
cpus_allowed=2
rw=randread

我不知道这是怎么回事。


这是 test1 的 fio 测试输出

job1: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64
fio-2.2.10
Starting 1 thread

job1: (groupid=0, jobs=1): err= 0: pid=6924: Mon Jan 29 20:14:33 2018
  read : io=15139MB, bw=1513.8MB/s, iops=387516, runt= 10001msec
    slat (usec): min=0, max=42, avg= 1.97, stdev= 1.12
    clat (usec): min=5, max=1072, avg=162.70, stdev=20.17
     lat (usec): min=6, max=1073, avg=164.74, stdev=20.39
    clat percentiles (usec):
     |  1.00th=[  141],  5.00th=[  145], 10.00th=[  149], 20.00th=[  151],
     | 30.00th=[  155], 40.00th=[  157], 50.00th=[  159], 60.00th=[  161],
     | 70.00th=[  165], 80.00th=[  169], 90.00th=[  179], 95.00th=[  211],
     | 99.00th=[  229], 99.50th=[  262], 99.90th=[  318], 99.95th=[  318],
     | 99.99th=[  334]
    lat (usec) : 10=0.01%, 20=0.01%, 50=0.02%, 100=0.03%, 250=99.35%
    lat (usec) : 500=0.60%, 1000=0.01%
    lat (msec) : 2=0.01%
  cpu          : usr=22.32%, sys=77.64%, ctx=102, majf=0, minf=421
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued    : total=r=3875556/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
   READ: io=15139MB, aggrb=1513.8MB/s, minb=1513.8MB/s, maxb=1513.8MB/s, mint=10001msec, maxt=10001msec

Disk stats (read/write):
  nvme0n1: ios=3834624/0, merge=0/0, ticks=25164/0, in_queue=25184, util=99.61% 

这是 test2(3cores) 的 fio 输出

job1: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64

job2: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64

job3: (g=0): rw=randread, bs=4K-4K/4K-4K/4K-4K, ioengine=libaio, iodepth=64

fio-2.2.10
Starting 3 threads

job1: (groupid=0, jobs=1): err= 0: pid=6968: Mon Jan 29 20:14:53 2018
  read : io=10212MB, bw=1021.2MB/s, iops=261413, runt= 10001msec
    slat (usec): min=1, max=140, avg= 2.49, stdev= 1.23
    clat (usec): min=4, max=970, avg=241.78, stdev=138.10
     lat (usec): min=7, max=972, avg=244.35, stdev=138.09
    clat percentiles (usec):
     |  1.00th=[   17],  5.00th=[   25], 10.00th=[   33], 20.00th=[   64],
     | 30.00th=[  135], 40.00th=[  225], 50.00th=[  306], 60.00th=[  330],
     | 70.00th=[  346], 80.00th=[  366], 90.00th=[  390], 95.00th=[  410],
     | 99.00th=[  438], 99.50th=[  446], 99.90th=[  474], 99.95th=[  502],
     | 99.99th=[  668]
    lat (usec) : 10=0.01%, 20=2.03%, 50=14.39%, 100=9.67%, 250=16.14%
    lat (usec) : 500=57.71%, 750=0.05%, 1000=0.01%
  cpu          : usr=17.32%, sys=71.84%, ctx=182182, majf=0, minf=318
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued    : total=r=2614396/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=64
job2: (groupid=0, jobs=1): err= 0: pid=6969: Mon Jan 29 20:14:53 2018
  read : io=10540MB, bw=1053.1MB/s, iops=269802, runt= 10001msec
    slat (usec): min=1, max=35, avg= 1.93, stdev= 0.97
    clat (usec): min=5, max=903, avg=234.55, stdev=139.14
     lat (usec): min=7, max=904, avg=236.56, stdev=139.13
    clat percentiles (usec):
     |  1.00th=[   16],  5.00th=[   22], 10.00th=[   30], 20.00th=[   57],
     | 30.00th=[  112], 40.00th=[  207], 50.00th=[  298], 60.00th=[  330],
     | 70.00th=[  346], 80.00th=[  362], 90.00th=[  386], 95.00th=[  402],
     | 99.00th=[  426], 99.50th=[  438], 99.90th=[  462], 99.95th=[  494],
     | 99.99th=[  628]
    lat (usec) : 10=0.01%, 20=3.22%, 50=14.51%, 100=10.76%, 250=15.48%
    lat (usec) : 500=55.97%, 750=0.05%, 1000=0.01%
  cpu          : usr=26.08%, sys=59.08%, ctx=377522, majf=0, minf=326
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued    : total=r=2698293/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=64
job3: (groupid=0, jobs=1): err= 0: pid=6970: Mon Jan 29 20:14:53 2018
  read : io=10368MB, bw=1036.8MB/s, iops=265406, runt= 10001msec
    slat (usec): min=1, max=102, avg= 2.48, stdev= 1.24
    clat (usec): min=5, max=874, avg=238.10, stdev=139.10
     lat (usec): min=7, max=877, avg=240.66, stdev=139.09
    clat percentiles (usec):
     |  1.00th=[   18],  5.00th=[   27], 10.00th=[   39], 20.00th=[   72],
     | 30.00th=[  113], 40.00th=[  193], 50.00th=[  290], 60.00th=[  330],
     | 70.00th=[  350], 80.00th=[  370], 90.00th=[  398], 95.00th=[  414],
     | 99.00th=[  442], 99.50th=[  454], 99.90th=[  474], 99.95th=[  498],
     | 99.99th=[  628]
    lat (usec) : 10=0.01%, 20=1.51%, 50=12.00%, 100=13.78%, 250=17.81%
    lat (usec) : 500=54.84%, 750=0.05%, 1000=0.01%
  cpu          : usr=17.96%, sys=71.88%, ctx=170809, majf=0, minf=319
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=0.1%, 32=0.1%, >=64=99.9%
    submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.1%, >=64=0.0%
     issued    : total=r=2654335/w=0/d=0, short=r=0/w=0/d=0, drop=r=0/w=0/d=0
     latency   : target=0, window=0, percentile=100.00%, depth=64

Run status group 0 (all jobs):
   READ: io=31121MB, aggrb=3111.9MB/s, minb=1021.2MB/s, maxb=1053.1MB/s, mint=10001msec, maxt=10001msec

Disk stats (read/write):
  nvme0n1: ios=7883218/0, merge=0/0, ticks=1730536/0, in_queue=1763060, util=99.52%

【问题讨论】:

你为什么说1516.7MB/s的单核基准测试结果作为“保证”或“限制”?唯一真正令人惊讶的是超过了制造商的性能数字。但是你确定没有操作系统缓存发生吗? (我没有使用fio,所以如果不同的设置可能导致缓存命中,请使用 IDK)。或者,英特尔的性能数字可能有些保守,并且每个型号都保证能够在新的时候达到这个数字,但有些甚至更快。 您也没有指定 CPU 型号或频率(例如 Haswell 2.4GHz?Skylake 4GHz?至少给我们一个 Xeon E5-xxx v4 编号或其他东西),或者您拥有哪种 Intel SSD 750 (不同容量的型号有不同的额定速度和实际速度)。 感谢您的回答。 cpu:Intel(R) Xeon(R) CPU E5-2650 v3 @ 2.3GHZ,ssd:Intel 固态硬盘 750 系列,400GB,20nm Intel NAND 闪存 MLC。 NVMe PCIe 3.0*4 附加卡。是的。当我创建 fio 文件时,我可以在启动 I/O 之前使要使用的文件的缓冲区/页面缓存部分无效。 我使用 O_DIRECT 标志(非缓冲 IO)绕过页面缓存并使用 linux 原生异步 I/O 请求。 感谢您的回答。几天前我听说过“预处理”(与预热相同)。在基准测试之前,我使用顺序写入写入了 50% 的 ssd 容量。在那之后,我看到它工作得很好。我写了 50% 因为我不得不避免 GC。非常感谢。内部缓存可能是个问题。但是 3000MB/s 太大了,无法解释。但它有助于我理解 ssd 的内部机制。谢谢 【参考方案1】:

嗯……

@peter-cordes 很好地说明了(设备)缓存。进行 Google 搜索会返回 https://www.techspot.com/review/984-intel-ssd-750-series/,其中包含以下内容:

板载的还有五个美光 D9PQL DRAM 芯片,用作 1.25GB 缓存,规格上说这是 DDR3-1600 内存。

鉴于您将 fio 限制为在相同的 256MByte 区域中为所有线程工作,因此您的所有 I/O 很可能很容易放入设备的缓存中。除了自然方式之外,没有专门的方法可以丢弃 设备的 缓存(与 Linux 的缓冲区缓存相反),因此我建议您将工作区域显着扩大(例如 10s - 100s GB)以减少一个线程的数据被另一个线程的访问预取的几率。

另外,我会问“在您读回 SSD 之前,您将哪些数据放到 SSD 上”? SSD 通常是“薄”的,因为它们可以知道从未写入过的区域或已被告知某个区域已被明确丢弃的区域。因为从这些区域读取数据意味着 SSD 几乎不需要做任何工作,并且可以非常快速地返回数据(就像操作系统从稀疏文件中的孔读取数据时所做的那样)。在“现实生活”中,您很少会选择阅读从未写过的内容,因此这样做会扭曲您的结果。

【讨论】:

感谢您的回答。几天前我听说过“预处理”(与预热相同)。在进行基准测试之前,我使用顺序写入写入了 50% 的 ssd 容量。在那之后,我看到它工作得很好。我写了 50% 因为我不得不避免 GC。非常感谢。

以上是关于使用多核时是不是可能超出带宽限制?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以限制 Amazon S3 使用的带宽?

怎样在 Linux 中限制网络带宽使用

使用 httpclient 限制下载的带宽使用

服务器带宽限制10M独享,为何有时候会跑超呢?

trigger.io 如何处理文件上传请求中的带宽限制、超时和重试?

使用mod_throttle模块限制web服务连接数和带宽