免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123
最近访问板块 发新帖
楼主: dulao5
打印 上一主题 下一主题

我的memcpy还是不如标准库的厉害 [复制链接]

论坛徽章:
0
21 [报告]
发表于 2006-12-29 11:03 |只看该作者
INTEL 上的REPZ MOVSB
快。memcpy等就可能优化成了这些。
用C写的慢。4个字节一起做也快不了多少

论坛徽章:
0
22 [报告]
发表于 2006-12-29 11:04 |只看该作者
嗯,看起来的确是这样, MOVSB指令就是为了移动串而生的,用它的确应该快.

论坛徽章:
0
23 [报告]
发表于 2006-12-30 00:12 |只看该作者
原帖由 星尘细雨 于 2006-12-29 10:18 发表
使用了mmx/sse/sse2的汇编来写memcpy肯定是更快的,
就是在非x86的CPU移植麻烦,
还有我记得性能还和cpu有关,
Intel的cpu在执行sse2指令比amd的cpu的sse2指令快。

既然提到 MMX 指令,就贴一段使用MMX指令copy内存块的代码:

  1. // block copy: copy a number of DWORDs from DWORD aligned source
  2. // to DWORD aligned destination using cacheable stores.
  3. __asm {
  4.     MOV ESI, [src_ptr]             ;pointer to src, DWORD aligned
  5.     MOV EDI, [dst_ptr]             ;pointer to dst, DWORD aligned
  6.     MOV ECX, [blk_size]             ;number of DWORDs to copy
  7.     PREFETCH (ESI)                     ;PREFetch first src cache line
  8.     CMP ECX, 1                     ;less than one DWORD to copy ?
  9.     JB $copydone2_cc             ;yes, must be no DWORDs to copy, done
  10.     TEST EDI, 7                     ;dst QWORD aligned?
  11.     JZ $dstqaligned2_cc             ;yes
  12.     MOVD MM0, [ESI]                     ;read one DWORD from src
  13.     MOVD [EDI], MM0             ;store one DWORD to dst
  14.     ADD ESI, 4                    ;src++
  15.     ADD EDI, 4                    ;dst++
  16.     DEC ECX                     ;number of DWORDs to copy

  17. $dstqaligned2_cc:
  18.     MOV EBX, ECX                     ;number of DWORDs to copy
  19.     SHR ECX, 4                     ;number of cache lines to copy
  20.     JZ $copyqwords2_cc             ;no whole cache lines to copy, maybe QWORDs
  21.     PREFetchm (ESI,64)             ;PREFetch src cache line one ahead
  22.     PREFetchmlong (ESI,128)     ;PREFetch src cache line two ahead

  23.     ALIGN 16                     ;align loop for optimal performance

  24. $cloop2_cc:
  25.     PREFetchmlong (ESI, 192)    ;prefetch cache line three ahead
  26.     MOVQ MM0, [ESI]             ;load first QWORD in cache line from src
  27.     ADD EDI, 64                     ;src++
  28.     MOVQ MM1, [ESI+8]             ;load second QWORD in cache line from src
  29.     ADD ESI, 64                     ;dst++
  30.     MOVQ MM2, [ESI-48]             ;load third QWORD in cache line from src
  31.     MOVQ [EDI-64], MM0             ;store first DWORD in cache line to dst
  32.     MOVQ MM0, [ESI-40]             ;load fourth QWORD in cache line from src
  33.     MOVQ [EDI-56], MM1             ;store second DWORD in cache line to dst
  34.     MOVQ MM1, [ESI-32]             ;load fifth QWORD in cache line from src
  35.     MOVQ [EDI-48], MM2             ;store third DWORD in cache line to dst
  36.     MOVQ MM2, [ESI-24]             ;load sixth QWORD in cache line from src
  37.     MOVQ [EDI-40], MM0             ;store fourth DWORD in cache line to dst
  38.     MOVQ MM0, [ESI-16]             ;load seventh QWORD in cache line from src
  39.     MOVQ [EDI-32], MM1             ;store fifth DWORD in cache line to dst
  40.     MOVQ MM1, [ESI-8]             ;load eight QWORD in cache line from src
  41.     MOVQ [EDI-24], MM2             ;store sixth DWORD in cache line to dst
  42.     MOVQ [EDI-16], MM0             ;store seventh DWORD in cache line to dst
  43.     DEC ECX                     ;count--
  44.     MOVQ [EDI-8], MM1             ;store eighth DWORD in cache line to dst
  45.     JNZ $cloop2_cc                     ;until no more cache lines to copy

  46. $copyqwords2_cc:
  47.     MOV ECX, EBX                     ;number of DWORDs to copy
  48.     AND EBX, 0xE                     ;number of QWORDS left to copy * 2
  49.     JZ $copydword2_cc             ;no QWORDs left, maybe DWORD left

  50.      ALIGN 16                   ;align loop for optimal performance

  51. $qloop2_cc:
  52.     MOVQ MM0, [ESI]             ;read QWORD from src
  53.     MOVQ [EDI], MM0             ;store QWORD to dst
  54.     ADD ESI, 8                     ;src++
  55.     ADD EDI, 8                     ;dst++
  56.     SUB EBX, 2                     ;count--
  57.     JNZ $qloop2_cc                     ;until no more QWORDs left to copy

  58. $copydword2_cc:
  59.     TEST ECX, 1                     ;DWORD left to copy ?
  60.     JZ $copydone2_cc             ;nope, we’re done
  61.     MOVD MM0, [ESI]             ;read last DWORD from src
  62.     MOVD [EDI], MM0             ;store last DWORD to dst

  63. $copydone2_cc:
  64.     FEMMS     ;clear MMX state
  65. }
复制代码


当复制块大于 512 字节时,使用以上代码才有价值


另一个更强悍的手法是使用: 128 位的 xmm 指令
  1. movdqa    xmm0,    [rdx+r8*8]         ; Load
  2. movntdq   [rcx+r8*8], xmm0            ; Store
  3. movdqa    xmm1, [rdx+r8*8+16]      ; Load
  4. movntdq   [rcx+r8*8+16], xmm1      ; Store
复制代码

论坛徽章:
0
24 [报告]
发表于 2006-12-30 08:57 |只看该作者
这种效率很诡异,我认为这些优化中,真值得去做的,就是把byte复制转化成word复制,这是跨平台的方法,而且绝大多数时候都能获得大幅度的效率提升。有时候,asm未必就比C快。
我测试的结果是,哪怕是asm优化过的,在拷贝的大小不同时效率也是不同的,很难说哪个更好。
另外,ia32上的串操作指令未必快,而mmx/sse这些指令又不通用。
代码上的优化还是适可而止的好,过度优化的代码没有生命力。

论坛徽章:
2
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:56:11
25 [报告]
发表于 2006-12-30 20:29 |只看该作者
不知使用汇编代码如何?
mov di,dest
mov si,src
mov cx,size
cld
rep movsd
不考虑重叠情况

论坛徽章:
0
26 [报告]
发表于 2006-12-30 20:59 |只看该作者

回复 25楼 cobras 的帖子

以前有Intel提供了相关优化的讲义,其间是讲到了C有些地方的写法,有很大的讲究
至于WimmX优化指令等,还是做浮点,积分很牛的哟。内存拷贝对系统而言,是可
以优化的,优化可以针对块拷贝,如512对齐等,具体要看应用了,有些需要大块对
齐,有些是线性的,如果系统允许,地接内存重映射就可以了。具体实现,还与OS的
内存管理有关。

如需大块线性空间,但用户空间已经不可能申请太多时,这时内存管理算法比拷贝可
能更耗时间了。当然,最快也无非DMA,锁存,传输,解锁,且最后换算出来,一定
是线性最好。你想想,如果真要while什么的,一定会慢下来。以后计算机最好用硬
件设计典型的加速器,且有多个适应逻辑,支持4K/BYTE/4M等单位数据迁移。

如果你需要4MB,直接在最短的1个周期中映射过去,力争在10个周期内处理完数据
(POST)。

唉,这些应用与实际要求相结合最好。至于memcpy,一般而言,就用libc的就可以了。
要求同步数据或其它高级应用,当然直接是你管理内存最好。不是以后有高带内存与
NOR一样了吗?可读,可写,可保存,设计一块区域专用于内存拷贝,还可异步完成。
双核心,系统也这样设计,一定是很高效了。
SEND DATA -> EXT LOCK
SEND MSG  -> DATA READY ->READ EXT LOCK DATA->NEXT OP
NEXT OP

扯得太远了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP