在 Windows 8.1 中,我使用 Robocopy 将 2 台服务器的数据保存到专用 PC 的存储空间中。数据量为 4,110 个文件夹中的 147,314 个文件(66,841,845,760 字节)。
涉及的 3 台 PC 均配备 4 核 i7 CPU,并处于 1 Gb 网络中。目标的存储空间(镜像并条带化在 D: 上)是使用 4 x 4 TB JBOD 机箱实现的。
由于 CPU 有 4 个核心和超线程,我预计 Robocopy 开关 /MT:8 将工作得最好,并且由于无益的线程管理,超过 8 个线程将会过度。
我对此进行了测试。我在此处列出了第四个测试系列的数据(持续时间以 mm:ss 为单位):
1 thread: 59:19
2 threads: 39:12
4 threads: 29:13
8 threads: 24:36
16 threads: 24:19
32 threads: 24:27
当然,使用 16 个线程的几秒钟可以忽略不计,但是它们是一致的在所有测试系列中,也就是说,不是因为少于 16 个线程的测试负载更大(除非在所有 4 个测试系列中都是这种情况)。还要注意,32 个线程几乎总是比 8 个线程快一点。
问题:在具有 4 个超线程核心的 i7 上,使用 16 个线程比使用 8 个线程更有效,这是什么技术原因?
答案1
TL;dr 版本:如果您正在执行高度 CPU 密集型的操作,例如使用 Handbrake 转码视频,那么您不会希望使用比 CPU 更多的内核,因为这样就无处可做工作了。在这种情况下,大多数线程将花费 90% 的时间处于休眠状态,等待读取或写入,因此拥有更多线程是可行的为了你而不是反对。
复制文件并不是一项特别依赖 CPU 的任务。虽然拥有更多核心可能有助于防止其他任务阻塞您的复制工具,但每个线程在每个核心上的运行率不太可能接近 100%。
每个复制线程都会向硬盘发送读取请求,然后在等待读取请求完成时进入休眠状态。旋转的锈盘通常寻道时间为 9 毫秒,从 CPU 角度来看,这几乎是永恒的时间,而复制任务不会只是旋转着说“准备好了吗?”并浪费 CPU 周期。这样做会将该线程锁定在 100% CPU 上并浪费资源。不会,实际发生的情况是线程发出读取请求,然后线程进入休眠状态,直到读取完成并且数据准备好进行下一步。
与此同时,另一个线程也做了同样的事情,在读取时被阻塞并进入休眠状态。这发生在您的所有 16 个线程上。(实际上,您的读取和写入将在随机时间发生,因为它们不同步,但您明白我的意思)
一旦某个线程准备好了数据,Windows 就会重新安排它并开始处理它以进行写入。就线程而言,过程是相同的。它说“将此数据写入位置 y 的文件 x”,然后 Windows 获取数据并取消安排线程。Windows 会在后台工作以确定文件的位置,移动数据(可能通过网络移动,从而增加更多毫秒的延迟),然后在写入成功后将控制权返回给线程。
没有一个线程会一直在 CPU 核心上燃烧,因此线程数多于 CPU 数不是问题。没有线程会长时间处于唤醒状态而导致出现问题。
如果您只有一个 CPU,并且还有许多其他线程在运行,那么 CPU 可能会成为瓶颈,但是在具有这种工作负载的多核系统中,如果 CPU 是问题所在,我会感到惊讶。
您更有可能遇到硬盘性能瓶颈,并达到驱动器上读取或写入缓冲区的队列深度。通过使用更多线程,您正在推动某物无论是磁盘还是网络,其极限都是如此,找出最佳线程数的唯一方法就是按照您已经做过的事情进行实验。
在具有 SSD 到 SSD 复制的系统上,我怀疑线程数较少可能会更好,因为与从旋转锈蚀 HDD 复制文件、通过网络推送并写入旋转锈蚀相比,延迟会更少,但我没有证据支持这种假设。