使用现代编译器在C++中使用"memset"功能的状态

rle*_*lut 19 c c++ memory optimization

语境:

不久之前,我偶然发现了Alexandrescu的2001年DDJ文章:http: //www.ddj.com/cpp/184403799

它是关于比较各种方法来初始化缓冲区到某个值.就像"memset"对单字节值的作用一样.他比较了各种实现(memcpy,显式"for"循环,duff的设备),并没有真正找到所有数据集大小和所有编译器的最佳候选者.

引用:

所有这一切都有一个非常深刻和悲伤的认识.我们是在2001年,即Space Odyssey的一年.(...)开箱即用,看看我们 - 50年后,我们仍然不擅长填充和复制记忆.

题:

  1. 有没有人有关于这个问题的最新信息?最近的GCC和Visual C++实现是否比7年前表现更好?
  2. 我正在编写具有5年(可能超过10年)的生命周期的代码,它将处理数组的大小从几个字节到几百兆字节.我不能假设我现在的选择在5年内仍然是最优的.我该怎么办:
    • a)使用系统的memset(或等效的)并忘记最佳性能或假设运行时和编译器将为我处理这个问题.
    • b)在各种数组大小和编译器上一劳永逸地进行基准测试,并在几个例程之间在运行时切换.
    • c)在程序初始化时运行基准测试,并在运行时根据准确的(?)数据进行切换.

编辑:我正在研究图像处理软件.我的数组项目是POD,每毫秒都很重要!

编辑2:感谢您的第一个答案,这里有一些额外的信息:

  • 缓冲区初始化可能占某些算法总运行时间的20%-40%.
  • 该平台可能在未来5年内有所不同,尽管它将保持"最快的CPU可以从DELL购买"类别.编译器将是某种形式的GCC和Visual C++.雷达上没有嵌入式东西或异国情调的架构
  • 我想听听那些在MMX和SSE出现时不得不更新软件的人,因为当"SSE2015"可用时我将不得不这样做...... :)

Rob*_*ker 10

DDJ文章承认memset是最好的答案,并且比他试图实现的要快得多:

关于C的内存操作函数memset,memcpy和memcmp有一些神圣不可侵犯的东西.它们很可能由编译器供应商高度优化,以至于编译器可能检测到对这些函数的调用并用内联汇编程序指令替换它们 - 这就是MSVC的情况.

因此,如果memset适合您(即您使用单个字节初始化),则使用它.

虽然每毫秒可能有效,但您应该确定在设置内存时丢失执行时间的百分比.考虑到您还有很多有用的工作,它可能非常低(1或2%??).鉴于优化工作可能会在其他地方获得更好的回报率.

  • 在某些算法运行中,临时"辅助"数组的初始化可能占总运行时间的20%到40%.而且我的数据通常是多字节的,因此memset在这种情况下不起作用(我已经将它用于单字节数据). (2认同)

Zoo*_*oba 8

MASM论坛有很多令人难以置信的汇编语言的程序员/谁已经完全击败这个问题到死亡爱好者(必须通过实验室看看).结果很像克里斯托弗的反应:SSE对于大型,对齐的缓冲区而言是令人难以置信的,但是下降到最终会达到如此小的尺寸,以至于基本for循环同样快.


Chr*_*her 5

Memset/memcpy主要是用基本指令集编写的,因此可以通过专门的SSE例程来表现,而另一方面,它强制执行某些对齐约束.

但要将其减少到列表:

  1. 对于数据集<=几百千字节,memcpy/memset比你可以模拟的任何东西都要快.
  2. 对于数据集>兆字节,使用memcpy/memset的组合来获得对齐,然后使用您自己的SSE优化例程/回退来优化来自Intel等的例程.
  3. 在启动时强制对齐并使用您自己的SSE例程.

此列表仅适用于需要演奏的场合.太小/或一次初始化的数据集不值得麻烦.

是一个来自AMD的memcpy的实现,我找不到描述代码背后概念的文章.


Pau*_*lin 4

d) 承认尝试在初始化中玩“绝地思维把戏”会导致程序员损失更多的时间,而不是一些晦涩但快速的方法与明显而清晰的方法之间的累积毫秒差异。