自己写的memcpy内存对齐优化问题

SIWWC 2018-02-03 10:30:37
第一个函数我先让源地址对齐4字节,再一次4字节的复制,最后移动剩下的
void* memcpy_copy_align(void* dst, const void* src, size_t count) {
assert(dst);
assert(src);

int *dalign, *salign;
int nchunks, slice;
char* dstp = (char*)dst;
const char* srcp = (const char*)src;

if (dstp<srcp + count && dstp>srcp) {
dstp += count - 1;
srcp += count - 1;
for (; ((int)srcp & 3) != 0; count--) {
if (!count)
return dst;
*dstp-- = *srcp--;
}
*dstp = *srcp;
count--;

nchunks = count >> 2;
slice = count & 3;
if (nchunks) {
dalign = (int*)dstp;
salign = (int*)srcp;
while (nchunks--)
*--dalign = *--salign;
dstp = (char*)dalign;
srcp = (char*)salign;
}
while (slice--)
*--dstp = *--srcp;
}
else {
for (; ((int)srcp & 3) != 0; count--) {
if (!count)
return dst;
*dstp++ = *srcp++;
}

nchunks = count >> 2;
slice = count & 3;
if (nchunks) {
dalign = (int*)dstp;
salign = (int*)srcp;
while (nchunks--)
*dalign++ = *salign++;
dstp = (char*)dalign;
srcp = (char*)salign;
}
while (slice--)
*dstp++ = *srcp++;
}
return dst;
}

第二个函数我不管地址对齐,直接一次复制4字节,再复制剩下的
void* memcpy_copy(void* dst, const void* src, size_t count) {
assert(dst);
assert(src);

int *dalign, *salign;
int nchunks, slice;
char* dstp = (char*)dst;
const char* srcp = (const char*)src;

nchunks = count >> 2;
slice = count & 3;

if (dstp<srcp + count && dstp>srcp) {
dstp += count;
srcp += count;
if (nchunks) {
dalign = (int*)dstp;
salign = (int*)srcp;
while (nchunks--)
*--dalign = *--salign;
dstp = (char*)dalign;
srcp = (char*)salign;
}
while (slice--)
*--dstp = *--srcp;
}
else {
if (nchunks) {
dalign = (int*)dstp;
salign = (int*)srcp;
while (nchunks--)
*dalign++ = *salign++;
dstp = (char*)dalign;
srcp = (char*)salign;
}
while (slice--)
*dstp++ = *srcp++;
}
return dst;
}

第三个函数是全部一位一位移动
void* memcpy_copy_a(void* dst, const void* src, size_t count) {
assert(dst);
assert(src);

char* dstp = (char*)dst;
const char* srcp = (const char*)src;

if (dstp<srcp + count && dstp>srcp) {
dstp += count;
srcp += count;
while (count--)
*--dstp = *--srcp;
}
else {
while (count--)
*dstp++ = *srcp++;
}
return dst;
}

然后main函数测试
int main()
{
int i;
clock_t start;
int len = sizeof(char) * 1024 * 1024 * 512;
char* b = (char*)malloc(len + 2);
printf("%x\n", b);

start = clock();
memcpy_copy_align(b + 2, b, len);
printf("\n位对齐块移动时间差:%ld\n", clock() - start);

start = clock();
memcpy_copy(b + 2, b, len);
printf("\n位不对齐块移动时间差:%ld\n", clock() - start);

start = clock();
memcpy_copy_a(b + 2, b, len);
printf("\n位不对齐逐个时间差:%ld\n", clock() - start);

start = clock();
memcpy(b + 2, b, len);
printf("\n系统memcpy时间差:%ld\n\n", clock() - start);

return 0;
}

测试结果:



我最不解的是第一个和第二个函数,第一个我进行了位对齐再进行的块移动,就算因为对齐的额外开销没有达到优化的目的,也不应该比第二个函数慢那么多啊,不解
ps:是在vs2017 x86平台release模式下测试的
...全文
1030 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
晨星 2018-02-06
  • 打赏
  • 举报
回复
谢谢给分~~
paschen 2018-02-04
  • 打赏
  • 举报
回复
引用 5 楼 SIWWC的回复:
[quote=引用 3 楼 paschen 的回复:] 程序运行速度除了算法外还和很多有关,如CPU Cache等,一个可能的原因是,你第一次memcpy时,整个BUFFER都是在内存中,而之后再进行memcpy时,数据已经加载到了CPU缓存中了,这时再进行操作命中概率更大效率更高,你可以试下调整下几个输出的顺序看有没变化
嗯嗯,真的变快了,请问有没有什么这方面的书籍推荐一下呢 谢谢!!![/quote] http://vdisk.weibo.com/s/zi0aI3JYCoC1m
SIWWC 2018-02-04
  • 打赏
  • 举报
回复
引用 3 楼 paschen 的回复:
程序运行速度除了算法外还和很多有关,如CPU Cache等,一个可能的原因是,你第一次memcpy时,整个BUFFER都是在内存中,而之后再进行memcpy时,数据已经加载到了CPU缓存中了,这时再进行操作命中概率更大效率更高,你可以试下调整下几个输出的顺序看有没变化
嗯嗯,真的变快了,请问有没有什么这方面的书籍推荐一下呢 谢谢!!!
SIWWC 2018-02-04
  • 打赏
  • 举报
回复
引用 1 楼 steedhorse 的回复:
没细看,只是好奇会不会第一个函数把处理器的cache给预热了。试着把第一个函数执行两遍,看看有没有不同?

真的也,看到运行结果时我觉得太神奇了,竟然真的第二遍变快了



想再问一下有没有关于这方面的书籍推荐呢

非常感谢!!!

SIWWC 2018-02-04
  • 打赏
  • 举报
回复
引用 6 楼 paschen 的回复:
[quote=引用 5 楼 SIWWC的回复:][quote=引用 3 楼 paschen 的回复:] 程序运行速度除了算法外还和很多有关,如CPU Cache等,一个可能的原因是,你第一次memcpy时,整个BUFFER都是在内存中,而之后再进行memcpy时,数据已经加载到了CPU缓存中了,这时再进行操作命中概率更大效率更高,你可以试下调整下几个输出的顺序看有没变化
嗯嗯,真的变快了,请问有没有什么这方面的书籍推荐一下呢 谢谢!!![/quote] http://vdisk.weibo.com/s/zi0aI3JYCoC1m[/quote] 谢谢你推荐的书籍
SIWWC 2018-02-04
  • 打赏
  • 举报
回复
引用 7 楼 paschen 的回复:
此外,memcpy要求是源和目的是不重叠的,所以你的测试准确的说是有问题的
嗯嗯,明白了,memcpy是用来复制不重叠地址的,有地址重叠的则用memmove
paschen 2018-02-04
  • 打赏
  • 举报
回复
此外,memcpy要求是源和目的是不重叠的,所以你的测试准确的说是有问题的
paschen 2018-02-04
  • 打赏
  • 举报
回复
程序运行速度除了算法外还和很多有关,如CPU Cache等,一个可能的原因是,你第一次memcpy时,整个BUFFER都是在内存中,而之后再进行memcpy时,数据已经加载到了CPU缓存中了,这时再进行操作命中概率更大效率更高,你可以试下调整下几个输出的顺序看有没变化
晨星 2018-02-03
  • 打赏
  • 举报
回复
没细看,只是好奇会不会第一个函数把处理器的cache给预热了。试着把第一个函数执行两遍,看看有没有不同?
晨星 2018-02-03
  • 打赏
  • 举报
回复
或者把第1个,第2个函数的先后次序颠倒下看看会不会有变化。

24,860

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧