优化内存 在C++中有更快的备选备忘录()吗?p>

优化内存 在C++中有更快的备选备忘录()吗?p>,c++,optimization,memcpy,C++,Optimization,Memcpy,对于一个非常类似的问题(关于memset())的回答也适用于这里 它基本上是说编译器为memcpy()/memset()-生成一些非常优化的代码,并根据对象的性质(大小、对齐方式等)生成不同的代码 >记住,只有代码> MycPy.()/Cudio> C++中的POD. 不可能。您的编译器/标准库可能会有一个非常高效和定制的memcpy实现。memcpy基本上是用于将内存的一部分复制到另一部分的最低api 如果您想要进一步的加速,请找到一种不需要任何内存复制的方法。这取决于您尝试执行的操作

对于一个非常类似的问题(关于
memset()
)的回答也适用于这里

它基本上是说编译器为
memcpy()
/
memset()
-生成一些非常优化的代码,并根据对象的性质(大小、对齐方式等)生成不同的代码


<> >记住,只有<>代码> MycPy.()/Cudio> C++中的POD.

不可能。您的编译器/标准库可能会有一个非常高效和定制的memcpy实现。memcpy基本上是用于将内存的一部分复制到另一部分的最低api


如果您想要进一步的加速,请找到一种不需要任何内存复制的方法。

这取决于您尝试执行的操作。。。如果它是一个足够大的memcpy,并且您只对副本进行少量写入,那么使用mmap_PRIVATE创建写时拷贝映射的mmap可能会更快。

根据您的平台,可能会有特定的用例,例如,如果您知道源和目标与缓存线对齐,并且大小是缓存线大小的整数倍。一般来说,大多数编译器都会为memcpy生成相当优化的代码

首先,一句忠告。假设编写标准库的人并不愚蠢。 如果有一种更快的方法来实现通用memcpy,他们早就做到了

第二,是的,有更好的选择

    在C++中,使用<代码> STD::复制< /C>函数。它也能做同样的事情,但1)更安全,2)在某些情况下可能更快。它是一个模板,这意味着它可以专门用于特定的类型,这使得它可能比一般的C memcpy更快
  • 或者,你可以利用你对具体情况的卓越知识。memcpy的实现者必须编写它,这样它在任何情况下都能很好地执行。如果您有关于需要它的情况的特定信息,您可能可以编写一个更快的版本。例如,您需要复制多少内存?它是如何对齐的?这可能会让您为这种特定情况编写更高效的memcpy。但在大多数其他情况下,它都不会那么好(如果它能奏效的话)

我不确定使用默认memcpy是否始终是最佳选择。我看到的大多数memcpy实现都倾向于在一开始就尝试对齐数据,然后进行对齐拷贝。如果数据已经对齐,或者非常小,那么这是在浪费时间

有时,有专门的字拷贝、半字拷贝、字节拷贝memcpy是有益的,只要它对缓存没有太大的负面影响

此外,您可能希望对实际分配算法进行更好的控制。在游戏行业中,人们编写自己的内存分配例程是非常常见的,不管工具链开发人员在开发它时花了多少精力。我看过的游戏几乎总是倾向于使用


不过,一般来说,优化memcpy是在浪费时间,因为毫无疑问,在应用程序中会有许多更容易加速的代码。

优化专家Agner Fog发布了优化内存函数:。不过这是GPL下的

不久前,Agner说这些函数应该取代GCC内置函数,因为它们速度更快。
我不知道从那以后是否已经做过了。

为了找到或编写一个快速内存复制例程,我们应该了解处理器是如何工作的

英特尔奔腾Pro之后的处理器执行“无序执行”。如果指令没有依赖关系,它们可能并行执行许多指令。但是,只有当指令仅与寄存器一起运行时,才会出现这种情况。如果它们使用内存运行,则会使用额外的CPU单元,称为“加载单元”(从内存读取数据)和“存储单元”(将数据写入内存)。大多数CPU有两个加载单元和一个存储单元,即它们可以并行执行两条从内存读取的指令和一条写入内存的指令(同样,如果它们彼此不影响的话)。这些单元的大小通常与最大寄存器大小相同——如果CPU有XMM寄存器(SSE)——它是16字节,如果它有YMM寄存器(AVX)——它是32字节,依此类推。所有读取或写入内存的指令都被转换为微操作(micro ops),这些微操作进入到micro ops的公共池,并在那里等待加载和存储单元能够为它们提供服务。一个加载或存储单元一次只能为一个微操作服务,而不管它需要加载或存储的数据大小是1字节还是32字节

所以,最快的内存拷贝将在最大大小的寄存器之间来回移动。对于支持AVX的处理器(但没有AVX-512),复制内存的最快方法是重复以下顺序,循环展开:

vmovdqa     ymm0,ymmword ptr [rcx]
vmovdqa     ymm1,ymmword ptr [rcx+20h]
vmovdqa     ymmword ptr [rdx],ymm0
vmovdqa     ymmword ptr [rdx+20h],ymm1
hplbsh之前发布的Google代码不是很好,因为他们在开始写回数据之前使用了所有8个xmm寄存器来保存数据,而这并不需要——因为我们只有两个加载单元和一个存储单元。因此,只有两个寄存器才能给出最佳结果。使用这么多寄存器并不能提高性能

内存复制例程还可以使用一些“高级”技术,如“预取”来指示处理器提前将内存加载到缓存中,以及“非时态写入”(如果要复制非常大的内存块,并且不需要立即读取输出缓冲区中的数据)、对齐写入与未对齐写入等

自2013年发布的现代处理器,如果在CPUID中有ERMS位,则具有所谓的“增强的rep movsb”,因此对于大内存拷贝,可以使用“rep movsb”–拷贝速度非常快,甚至比ymm寄存器更快,并且可以与缓存正常工作。然而,这条指令的启动成本非常高——大约35个周期,所以它只在大内存上支付