关于SSE优化内存拷贝的问题

肖尧19 技术经理,主程  2009-08-06 03:11:45
小弟汇编基础比较差,因工作需求需要实现一个内存拷贝优化的函数
自己参考资料写了个(思路比较简单 1次用够8个128bit的寄存器循环移动数据)
各位看看还有没有优化空间

另外主要的问题是 根据实际测试 结果 大于2M的数据 循环拷贝1000次 大概比memcpy快一倍
但是小于2M的数据块 就都比memcpy慢了 小块数据是否也有可能优化出比memcpy更佳的性能?
void memcpySSE(void* dest,const void* src,size_t _size)
{

__asm
{
//首先检测src地址是否16byte对齐
mov eax,src;
mov ebx,16;
mov edx,0;
div ebx;
cmp edx,0;
//edx非0则跳转
jnz addr_unaligned;
//采用地址对齐mov指令
//addr_aligned:
//数据块是否按128byte对齐
mov eax,_size;
mov ebx,128;
mov edx,0;
div ebx;

mov esi,src;
mov edi,dest;
aligned_loop:
//数据预取 32byte偏移的寻址 添充128byte的CPU CACHE
prefetchnta 128[ESI];
prefetchnta 160[ESI];
prefetchnta 192[ESI];
prefetchnta 224[ESI];

movdqa xmm0,0[ESI];//src to 寄存器
movdqa xmm1,16[ESI];
movdqa xmm2,32[ESI];
movdqa xmm3,48[ESI];
movdqa xmm4,64[ESI];
movdqa xmm5,80[ESI];
movdqa xmm6,96[ESI];
movdqa xmm7,112[ESI];

movntdq 0[EDI],xmm0;//寄存器 to dst
movntdq 16[EDI],xmm1;
movntdq 32[EDI],xmm2;
movntdq 48[EDI],xmm3;
movntdq 64[EDI],xmm4;
movntdq 80[EDI],xmm5;
movntdq 96[EDI],xmm6;
movntdq 112[EDI],xmm7;

add esi,128;
add edi,128;
dec eax;
jnz aligned_loop;
//aligned_loop_end:
//如果edx非0 操作剩余byte
mov ecx,edx;
rep movsb;
jmp memcpy_sse_end;
addr_unaligned:
mov eax,_size;
mov ebx,128;
mov edx,0;
div ebx;

mov esi,src;
mov edi,dest;
unaligned_loop:
prefetchnta 128[ESI];
prefetchnta 160[ESI];
prefetchnta 192[ESI];
prefetchnta 224[ESI];

movdqu xmm0,0[ESI];//src to 寄存器
movdqu xmm1,16[ESI];
movdqu xmm2,32[ESI];
movdqu xmm3,48[ESI];
movdqu xmm4,64[ESI];
movdqu xmm5,80[ESI];
movdqu xmm6,96[ESI];
movdqu xmm7,112[ESI];

movntdq 0[EDI],xmm0;//寄存器 to dst
movntdq 16[EDI],xmm1;
movntdq 32[EDI],xmm2;
movntdq 48[EDI],xmm3;
movntdq 64[EDI],xmm4;
movntdq 80[EDI],xmm5;
movntdq 96[EDI],xmm6;
movntdq 112[EDI],xmm7;

add esi,128;
add edi,128;
dec eax;
jnz unaligned_loop;
//unaligned_loop_end:
mov ecx,edx;
rep movsb;
memcpy_sse_end:
}

}
...全文
322 点赞 收藏 7
写回复
7 条回复
linguranus 2009年10月30日
我写了sun opensolaris libc strlen, strcmp, strcopy
还有moblin libc 的memcpy, memcmp, memset.
我确定这是准确的方法
回复 点赞
linguranus 2009年10月28日
1)对于 src, dst 完全 16byte 对奇, 对 一级cache size >= 2*datasize 的拷贝不要用prefetch 指令,只有当L1 cache size <= 2* data size 的时候使用 prefetcht0 , 但是这个命令会依据不同的架构而跨度不同 AMD和intel 不同的产品都会不同很烦琐需要你去测!
2)对不是 16byte对齐, 你需要用和并他们
3)当你的2*data size >= last level cache,请你使用 MOVNTDQ
回复 点赞
gzgzlxg 2009年08月11日
好像都走到极端了,楼主不妨研究自己的CPU,然后找出针对自己机器的拷贝方法来,至于你说小于2m的问题,那不妨分两条腿走路,2m以上,走你的路,2m以下走别的路。
回复 点赞
大熊猫侯佩 2009年08月07日
sse优化的例子网上有很多,这里也经常有人问,楼主搜索一下
回复 点赞
我啃 2009年08月07日
参见:
http://bbs.emath.ac.cn/archiver/?tid-348.html
回复 点赞
CopperBell 2009年08月07日
只能帮顶
回复 点赞
DarkChampion 2009年08月06日
up
回复 点赞
发动态
发帖子
汇编语言
创建于2007-08-27

1.9w+

社区成员

4.1w+

社区内容

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区公告
暂无公告