|
|
|
|
|
|
|
CPU架构
帖子发起人: Coding 发起时间: 2009-02-09 16:36 下午 回复: 2
|
帖子排序:
|
|
|
|
2009-02-09, 16:36 下午
|
Coding
注册: 2008-05-31
发 贴: 103
|
MOV和MOVS的效率问题?如何高效的拷贝内存中的数据?
|
|
|
|
在实现memory copy的时候,是用MOVS直接从memroy拷贝到memroy
还是用MOV先拷贝到register,然后再拷贝到memroy快呢?我想问题的根结在于MOVS需不需要把memory的内容先读到CPU里面来。
从我查到资料来看最快的方法是,合理的控制cache,然后用movq从cache中读取data到mmx register中,然后用movntq写到memory中。不知道是不是这样是最快的?
我的背景是这样的,需要在内核态完成1M的内存拷贝,越快越好了,因为每秒需要做60次这样的拷贝。这些内存(目标和源)实际上都是给集成显卡用的显存,软件本身不需要访问这些内存。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2009-02-09, 22:31 下午
|
格蠹老雷
注册: 2005-12-19
发 贴: 1,303
|
Re: MOV和MOVS的效率问题?如何高效的拷贝内存中的数据?
|
|
|
|
不知你是否已经读过优化手册(Intel 64 and IA-32 Architectures Optimization Reference Manual)的3.7.6节:REP Prefix and Data Movement
针对你描述的情况,先拷贝到通用寄存器肯定不可取。应该是使用REP MOVSD或者SIMD类型的指令。
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
2009-02-17, 16:14 下午
|
Coding
注册: 2008-05-31
发 贴: 103
|
Re: MOV和MOVS的效率问题?如何高效的拷贝内存中的数据?
|
|
|
|
一些进一步的研究和疑问。
先说问题,umd下如何能够分配Write combine的内存,我翻了下Win API没有发现合适的。在kmd下倒可以用MmAllocatePagesForMdlEx一类的函数指定memory的类型,诸如MmNonCached /MmCached / MmWriteCombined
再说研究,对于连续虚拟地址的大内存拷贝, 试验在一个atom cpu上做的,它有24k的L1级数据cache。
使用rep movsb,比如memcpy2是最慢的
使用rep movsd,比如memcpy3好一点。
最快的是用SSE指令movdqa和movntdq,这两个指令每次移动128bits,也就是16bytes的数据。比如memcpy4和memcpy7,这两个函数的区别在于memcpy7是使用prefetchnta自己处理cache, 与预料中不一样的是,memcpy7并没有比memcpy4快多少,有时候还慢,具体原因不明。
看了Intel的手册,以下因素对于拷贝数据的效率比较重要,
拷贝的粒度,越大越好,一次16bytes比4bytes好
提高cache命中率
地址对齐
使用Write combine写内存
其他的还有一些我也没理解的知识。
void memcpy2(void* Dst,void* Src,size_t Maxsize)
{
__asm
{
mov esi,[Src]
mov edi,[Dst]
mov ecx, [Maxsize]
rep movsb
}
}
void Mymemcpy3(void* Dst,void* Src,size_t Maxsize)
{
__asm
{
mov esi,[Src]
mov edi,[Dst]
mov ecx, [Maxsize]
shr ecx,2
rep movsd
}
}
void memcpy4(void* Dst,void* Src,size_t Maxsize)
{
__asm
{
mov esi,[Src]
mov edi,[Dst]
mov ecx, [Maxsize]
lea esi,[esi+ecx]
lea edi,[edi+ecx]
neg ecx
copyloop:
movdqa xmm0, qword ptr[esi+ecx]
movdqa xmm1, qword ptr[esi+ecx+16]
movdqa xmm2, qword ptr[esi+ecx+32]
movdqa xmm3, qword ptr[esi+ecx+48]
movdqa xmm4, qword ptr[esi+ecx+64]
movdqa xmm5, qword ptr[esi+ecx+80]
movdqa xmm6, qword ptr[esi+ecx+96]
movdqa xmm7, qword ptr[esi+ecx+112]
movntdq qword ptr[edi+ecx], xmm0
movntdq qword ptr[edi+ecx+16], xmm1
movntdq qword ptr[edi+ecx+32], xmm2
movntdq qword ptr[edi+ecx+48], xmm3
movntdq qword ptr[edi+ecx+64], xmm4
movntdq qword ptr[edi+ecx+80], xmm5
movntdq qword ptr[edi+ecx+96], xmm6
movntdq qword ptr[edi+ecx+112], xmm7
add ecx,128
jnz copyloop
sfence
emms
}
}
#define CACHEBLOCK 6000h
void Mymemcpy7(void* Dst,void* Src,size_t Maxsize)
{
__asm
{
mov esi,[Src]
mov edi,[Dst]
mov ecx, [Maxsize]
lea esi,[esi+ecx]
lea edi,[edi+ecx]
neg ecx
mainloop:
mov eax, CACHEBLOCK / 128
add ecx, CACHEBLOCK
prefetchloop:
prefetchnta [esi+ecx-64]
prefetchnta [esi+ecx-128]
sub ecx,128
dec eax
jnz prefetchloop
mov eax, CACHEBLOCK/128
copyloop:
movdqa xmm0, qword ptr[esi+ecx]
movdqa xmm1, qword ptr[esi+ecx+16]
movdqa xmm2, qword ptr[esi+ecx+32]
movdqa xmm3, qword ptr[esi+ecx+48]
movdqa xmm4, qword ptr[esi+ecx+64]
movdqa xmm5, qword ptr[esi+ecx+80]
movdqa xmm6, qword ptr[esi+ecx+96]
movdqa xmm7, qword ptr[esi+ecx+112]
movntdq qword ptr[edi+ecx], xmm0
movntdq qword ptr[edi+ecx+16], xmm1
movntdq qword ptr[edi+ecx+32], xmm2
movntdq qword ptr[edi+ecx+48], xmm3
movntdq qword ptr[edi+ecx+64], xmm4
movntdq qword ptr[edi+ecx+80], xmm5
movntdq qword ptr[edi+ecx+96], xmm6
movntdq qword ptr[edi+ecx+112], xmm7
add ecx,128
dec eax
jnz copyloop
or ecx,ecx
jnz mainloop
sfence
emms
}
}
|
|
|
IP 地址: 已记录
|
报告
|
|
|
|
高端调试 » 系统架构 » CPU架构 » Re: MOV和MOVS的效率问题?如何高效的拷贝内存中的数据?
|
|
|
|
|
|