是什么让Apple的PowerPC memcpy如此之快?

时间:2010-01-02 01:57:48

标签: optimization memcpy powerpc shark altivec

为了在PowerPC上寻找一个好的内存策略,我写了几个复制函数。使用具有高速缓存提示(dcb *)的Altivec或fp寄存器可以在大数据的简单字节复制循环中使性能提高一倍。最初很满意的是,我定期记忆,看看它的比较...比我最好的速度快10倍!我无意重写memcpy,但我希望从中学习并加速几个简单的图像过滤器,这些过滤器大部分时间将像素移入和移出内存。

鲨鱼分析显示它们的内部循环使用dcbt预取,有4个向量读取,然后是4个向量写入。在调整了我的最佳函数以便每次迭代运行64个字节之后,memcpy的性能优势仍然令人尴尬。我正在使用dcbz来释放带宽,Apple没有使用任何东西,但两个代码都倾向于在商店里犹豫不决。

prefetch
  dcbt future
  dcbt distant future
load stuff
  lvx image
  lvx image + 16
  lvx image + 32
  lvx image + 48
  image += 64
prepare to store
  dcbz filtered
  dcbz filtered + 32
store stuff
  stvxl filtered
  stvxl filtered + 16
  stvxl filtered + 32
  stvxl filtered + 48
  filtered += 64
repeat

有没有人对为什么非常相似的代码具有如此显着的性能差距有一些想法?我喜欢用真正的图像过滤器来腌制真实的图像过滤器!@ / p>

附加信息:所有数据都是矢量对齐的。我正在制作图像的过滤副本,而不是替换原始图像。该代码在PowerPC G4,G5和Cell PPU上运行。 Cell SPU版本已经非常快。

5 个答案:

答案 0 :(得分:7)

  

鲨鱼分析显示它们的内部循环使用dcbt预取,有4个向量读取,然后是4个向量写入。在调整我的最佳函数之后,每次迭代也会运行64个字节

我可能会说明显而已,但由于你在问题中没有提到以下内容,所以值得指出:

我敢打赌,Apple选择4个矢量读取后跟4个矢量写入与G5's pipeline and its management of out-of-order instruction execution in "dispatch groups"一样多,因为它具有神奇的64字节完美线条大小。您是否注意到Nick Bastin的链接bcopy.s中的线路跳过?这意味着开发人员考虑了G5如何使用指令流。如果你想重现相同的性能,一次读取64字节数据是不够的,你必须确保你的指令组充分填充(基本上,我记得指令最多可以分为五个独立的指令组,前四个是非跳转指令,第五个只允许跳转。细节更复杂)。

编辑:您可能也会对同一页上的以下段落感兴趣:

  

根据G4和G3,dcbz指令仍然对齐32位字节的内存段。但是,由于这不是G5上的完整缓存行,因此它不具备您可能希望的性能优势。为G5新引入的dcbzl指令将整个128字节的高速缓存行归零。

答案 1 :(得分:2)

我不确切知道你在做什么,因为我看不到你的代码,但Apple的秘诀是here

答案 2 :(得分:0)

也许是因为CPU缓存。尝试运行CacheGrind

  

Cachegrind是一个缓存探查器。它   执行详细的模拟   I1,D1和L2缓存在你的CPU和   所以可以准确地确定来源   缓存未命中代码。它   标识缓存未命中数,   记忆参考和说明   为每行源代码执行,   每个功能,每个模块和   整个计划摘要。它是有益的   使用任何语言编写的程序。   Cachegrind运行程序   比正常情况慢20-100倍。

答案 3 :(得分:0)

仍然没有答案,但你确认memcpy实际上正在移动数据吗?也许它只是重新映射写入。你仍然可以看到Shark中的内部memcpy循环作为第一页和最后一页的一部分被真正复制。

答案 4 :(得分:0)

正如另一个答案中所提到的,Apple在G5上定义的“dcbz”仅在32字节上运行,因此在具有128字节高速缓存行的G5上使用该指令会失去性能。您需要使用“dcbzl”来防止从内存中提取目标高速缓存行(并有效地将有用的读取内存带宽减少一半)。