我正在设计一个偶尔必须复制大量内存的实时系统。内存由非小区域组成,因此我预计复制性能将非常接近相关组件(CPU,RAM,MB)可以执行的最大带宽。这让我想知道现代商品机可以采用什么样的原始内存带宽?
如果我使用1个线程到memcpy()
,我的老化Core2Duo会给我1.5 GB / s(如果我memcpy()
同时使用两个核心,那么可以理解的更少。)虽然1.5 GB是相当数量的数据,我正在处理的实时应用程序将具有1/50秒的内容,这意味着30 MB。基本上,几乎没有。也许最糟糕的是,当我添加多个内核时,我可以处理更多数据而不会提高所需复制步骤的性能。
但是现在低端的Core2Due并不是很热门的东西。是否有任何网站在当前和近期硬件的原始内存带宽上都有信息,例如实际基准测试?
此外,为了在内存中复制大量数据,是否有任何快捷方式,或者memcpy()
是否会达到最佳状态?
考虑到一堆核心无所事事,但在很短的时间内尽可能多地重复内存,我能做的最好的是什么?
编辑:我仍在寻找有关原始内存复制性能的良好信息。我只是运行了我的旧memcpy()
基准。相同的机器和设置,现在提供2.5 GB / s ......
答案 0 :(得分:2)
在较新的CPU上,例如Nehalem,以及自Opteron以来的AMD,内存对于一个CPU是“本地的”,其中一个CPU可能有多个内核。也就是说,核心访问连接到其CPU的本地内存需要一定的时间,核心有更多时间访问远程内存,其中远程内存是其他CPU本地的内存。这称为非均匀内存访问或NUMA。为获得最佳的memcpy性能,您需要将BIOS设置为NUMA模式,将线程固定到内核,并始终访问本地内存。详细了解NUMA on wikipedia。
不幸的是,我不知道有关最新CPU和芯片组的memcpy性能的网站或最近的论文。你最好的选择可能是自己测试一下。
至于memcpy()
表现,有很多变化,具体取决于实施情况。例如,英特尔C库(或可能是编译器本身)的memcpy()
比Visual Studio 2005提供的快得多。至少在英特尔机器上。
您可以做的最佳内存副本取决于数据的对齐方式,您可以使用向量指令,还有页面大小等。实现好的memcpy()
令人惊讶,所以我建议在编写自己的实现之前尽可能多地查找和测试实现。如果您了解有关副本的更多细节,例如对齐和大小,那么可能能够比英特尔memcpy()
更快地实现某些功能。如果您想了解详细信息,可以从英特尔和AMD优化指南开始,或Agner Fog's software optimization pages。
答案 1 :(得分:1)
我认为你正在以错误的方式解决问题。我认为,目标是在不破坏实时性能的情况下导出数据的一致快照。不要使用硬件,使用算法。
您要做的是在数据之上定义日记系统。当您开始内存传输时,您有两个线程:原始的工作并认为它正在修改数据(但实际上只是写入日志),以及一个新的线程将旧的(未记录的)数据复制到一个单独的位置,所以它可以慢慢写出来。
当新线程完成后,您将其用于将数据集与日志合并,直到日志为空。当它完成后,旧线程可以返回直接与数据交互,而不是通过日志修改版本进行读/写。
最后,新线程可以转到复制的数据并开始慢慢将其传递给远程源。
如果您设置了这样的系统,只要您可以在日志充分到现实之前完成内存中的复制,就可以在正在运行的系统中实现任意大量数据的即时快照。时间系统无法跟上其处理需求。