windows - 32 位和 64 位进程之间的 memcpy 性能差异

标签 windows memory 64-bit cpu 32-bit

我们有配备 XP64 的 Core2 机器 (Dell T5400)。

我们观察到,在运行 32 位进程时, memcpy 的性能大约为 1.2GByte/s;但是 memcpy 在 64 位进程中 达到约2.2GByte/s(或2.4GByte/s 与英特尔编译器 CRT 的 memcpy)。虽然 最初的 react 可能只是解释这一点 由于可用的寄存器更广泛 在 64 位代码中,我们观察到我们自己的类似 memcpy SSE 汇编代码(应使用 128 位 宽负载存储,无论 32/64 位 该过程)展示了类似的上限 它实现的复制带宽。

我的问题是,这实际上有什么区别 由于 ? 32位进程是否必须跳过 一些额外的 WOW64 箍来获取内存?是不是什么东西 与 TLB 或预取器有关,或者......什么?

感谢您的任何见解。

也在 Intel forums 上提出.

最佳答案

我认为以下可以解释:

要将数据从内存复制到寄存器并返回内存,您可以这样做

mov eax, [address]
mov [address2], eax

这会将 32 位(4 字节)从地址移动到地址 2。 64 位模式下的 64 位也是如此

mov rax, [address]
mov [address2], rax

这会将 64 位 2 字节从地址移动到地址 2。根据英特尔的规范,“mov”本身,无论是 64 位还是 32 位,都具有 0.5 的延迟和 0.5 的吞吐量。延迟是指令通过流水线所需的时钟周期数,吞吐量是 CPU 在再次接受同一指令之前必须等待的时间。正如您所看到的,它每个时钟周期可以执行两个 mov,但是,它必须在两个 mov 之间等待半个时钟周期,因此它实际上每个时钟周期只能执行一个 mov(或者我在这里错了并且误解了这些术语?详见 PDF here)。

当然 mov reg, mem 可以超过 0.5 个周期,这取决于数据是在一级缓存还是二级缓存中,或者根本不在缓存中,需要从内存中抓取。但是,上面的延迟时间忽略了这个事实(正如我上面链接的 PDF 状态),它假设 mov 所需的所有数据都已经存在(否则延迟将增加从任何地方获取数据所需的时间)现在 - 这可能是几个时钟周期,并且完全独立于正在执行的命令,如第 482/C-30 页的 PDF 所述)。

有趣的是,mov 是 32 位还是 64 位都不起作用。这意味着除非内存带宽成为限制因素,否则 64 位 mov 与 32 位 mov 一样快,并且由于使用 64 位时将相同数量的数据从 A 移动到 B 只需要一半的 mov,因此吞吐量可以(理论上)是两倍高(事实并非如此,可能是因为内存不是无限快的)。

好的,现在您认为当使用更大的 SSE 寄存器时,您应该获得更快的吞吐量,对吧? AFAIK xmm 寄存器不是 256,而是 128 位宽,顺便说一句(reference at Wikipedia)。但是,您是否考虑过延迟和吞吐量?您要移动的数据是否 128 位对齐。根据这一点,您可以使用移动它

movdqa xmm1, [address]
movdqa [address2], xmm1

如果没有对齐

movdqu xmm1, [address]
movdqu [address2], xmm1

嗯,movdqa/movdqu 的延迟为 1,吞吐量为 1。因此指令的执行时间是普通 mov 的两倍,指令执行后的等待时间是普通 mov 的两倍。

还有一些我们甚至没有考虑到的事实是 CPU 实际上将指令拆分为微操作,并且它可以并行执行这些操作。现在它开始变得非常复杂......甚至对我来说太复杂了。

无论如何,根据经验,我知道向/从 xmm 寄存器加载数据比向/从普通寄存器加载数据要慢得多,因此您使用 xmm 寄存器加速传输的想法从一开始就注定要失败。实际上,我很惊讶 SSE memmove 最终并没有比正常的慢很多。

关于windows - 32 位和 64 位进程之间的 memcpy 性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/269408/

相关文章:

windows - 如何从 Windows Vista Complete PC 备份中提取文件?

c++ - windows删除正在运行的文件

windows - Webrick 和 Thin 在 Windows 中提供静态文件的速度非常慢。我怎样才能加快他们的速度?

PHP数组效率和内存澄清

java - 使用loadLibrary加载dll

C++ WinSock2 : WSA_INVALID_HANDLE on connect() call

java - Android 第三次从图库中选择图像时内存不足

html - 在同一页面上呈现 10 000 个链接

linux - 在Ubuntu Bionic 18.04 Xeon上安装docker

c# - 将 64 位数组转换为 Int64 或 ulong C#