你好(很抱歉我的英语不好),对于一些可移植性问题,我需要给自己写一个内存复制函数。但我的最大努力是比visual studio的2010标准memcpy慢40-70%。我也不知道为什么。接下来,您可以看到我的主复制循环,它复制所有128字节的数据块(来自function的所有其他代码在操作数量上都是有限的,可以假设为O(1))
MOVDQA XMM0,DQWORD PTR DS:[ESI]
MOVDQA XMM1,DQWORD PTR DS:[ESI+10]
MOVDQA XMM2,DQWORD PTR DS:[ESI+20]
MOVDQA XMM3,DQWORD PTR DS:[ESI+30]
MOVDQA DQWORD PTR DS:[EDI],XMM0
MOVDQA DQWORD PTR DS:[EDI+10],XMM1
MOVDQA DQWORD PTR DS:[EDI+20],XMM2
MOVDQA DQWORD PTR DS:[EDI+30],XMM3
MOVDQA XMM4,DQWORD PTR DS:[ESI+40]
MOVDQA XMM5,DQWORD PTR DS:[ESI+50]
MOVDQA XMM6,DQWORD PTR DS:[ESI+60]
MOVDQA XMM7,DQWORD PTR DS:[ESI+70]
MOVDQA DQWORD PTR DS:[EDI+40],XMM4
MOVDQA DQWORD PTR DS:[EDI+50],XMM5
MOVDQA DQWORD PTR DS:[EDI+60],XMM6
MOVDQA DQWORD PTR DS:[EDI+70],XMM7
LEA ESI,[ESI+80]
LEA EDI,[EDI+80]
DEC ECX
JNE SHORT 002410B9接下来,我在标准memcpy中找到了
MOVDQA XMM0,DQWORD PTR DS:[ESI]
MOVDQA XMM1,DQWORD PTR DS:[ESI+10]
MOVDQA XMM2,DQWORD PTR DS:[ESI+20]
MOVDQA XMM3,DQWORD PTR DS:[ESI+30]
MOVDQA DQWORD PTR DS:[EDI],XMM0
MOVDQA DQWORD PTR DS:[EDI+10],XMM1
MOVDQA DQWORD PTR DS:[EDI+20],XMM2
MOVDQA DQWORD PTR DS:[EDI+30],XMM3
MOVDQA XMM4,DQWORD PTR DS:[ESI+40]
MOVDQA XMM5,DQWORD PTR DS:[ESI+50]
MOVDQA XMM6,DQWORD PTR DS:[ESI+60]
MOVDQA XMM7,DQWORD PTR DS:[ESI+70]
MOVDQA DQWORD PTR DS:[EDI+40],XMM4
MOVDQA DQWORD PTR DS:[EDI+50],XMM5
MOVDQA DQWORD PTR DS:[EDI+60],XMM6
MOVDQA DQWORD PTR DS:[EDI+70],XMM7
LEA ESI,[ESI+80]
LEA EDI,[EDI+80]
DEC EDX
JNE SHORT 6B150A72正如您所看到的,这个周期与我自己的周期几乎相同,但是我的函数变得越来越慢(与std memcpy相比),需要复制的数据量越来越大。
谁能回答我的错误在哪里?
附言:这是我的main()代码
void main(void){
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
int* mas = new int[10000000];
for(int i = 0; i < 10000000; ++i)
mas[i] = i;
LARGE_INTEGER mmcpy = { 0 };
LARGE_INTEGER mmsse = { 0 };
for(int i = 0; i < 10000; ++i)
{
LARGE_INTEGER beforeMemcpy_sse, afterMemcpy_sse;
QueryPerformanceCounter(&beforeMemcpy_sse);
TestMemcpy_sse(mas, (char*)mas + 300000, 4400000);
QueryPerformanceCounter(&afterMemcpy_sse);
LARGE_INTEGER beforeMemcpy, afterMemcpy;
QueryPerformanceCounter(&beforeMemcpy);
memcpy(mas, (char*)mas + 300000, 4400000);
QueryPerformanceCounter(&afterMemcpy);
mmcpy.QuadPart += afterMemcpy.QuadPart - beforeMemcpy.QuadPart ;
mmsse.QuadPart += afterMemcpy_sse.QuadPart - beforeMemcpy_sse.QuadPart;
}
delete[] mas;
/*printf("Memcpy Time: %f\n", (afterMemcpy.QuadPart - beforeMemcpy.QuadPart) / (float)freq.QuadPart);
printf("SSE Memcpy Time: %f\n\n", (afterMemcpy_sse.QuadPart - beforeMemcpy_sse.QuadPart) / (float)freq.QuadPart);*/
printf("Memcpy Time: %f\n", mmcpy.QuadPart / ((float)freq.QuadPart * 10000));
printf("SSE Memcpy Time: %f\n\n", mmsse.QuadPart / ((float)freq.QuadPart * 10000));
system("pause");
}发布于 2011-09-09 07:27:05
您可能会看到缓存效果。根据缓存的大小,您可以在第一次使用memcpy函数测试时使用冷缓存复制mas数组的一个子集,然后在测试内置的memcpy时看到热缓存。
通常,当测量这样的代码的性能时,您应该对多次运行进行平均,并注意避免缓存影响,方法是使用比缓存大得多的数据集进行测试,或者使用故意小到足以放入缓存中的数据集进行测试,并在测试之前预热缓存。
发布于 2011-09-09 07:27:03
这是因为第二个memcpy正在访问缓存预热数据(由第一个memcpy预热)。您在一个5MB的区域内复制,然后再在该区域内复制-您的L3缓存可能为6MB-12MB。尝试交换副本的顺序,看看您会得到什么结果。:-)
https://stackoverflow.com/questions/7355195
复制相似问题