【也发一段memcpy】...

healer_kx 2010-01-06 01:38:45
我必须抱着学习的态度来问问了,因为前几天有朋友发了一段memcpy的代码,我觉得我曾经写过的代码,就显得很小儿科了。
但是很多现实问题,我依然不懂,想问问哪里有问题?或者可以改进。


void* Pz_memcpy(void* dest, void* src, size_t len)
{
size_t l = len / 8;
size_t m = len % 8;

int* si = (int*)src;
int* di = (int*)dest;
while (l--)
{
*di++ = *si++;
*di++ = *si++;
}

unsigned char* sc = (unsigned char*)si;
unsigned char* dc = (unsigned char*)di;

switch(m)
{
case 8: *dc++ = *sc++;
case 7: *dc++ = *sc++;
case 6: *dc++ = *sc++;
case 5: *dc++ = *sc++;
case 4: *dc++ = *sc++;
case 3: *dc++ = *sc++;
case 2: *dc++ = *sc++;
case 1: *dc++ = *sc++;
case 0:
default:
break;
}
return dest;
}


我确实没有考虑对齐等因素,因为不懂。。。
第二,我没有实现memmove的功能~
...全文
339 43 打赏 收藏 转发到动态 举报
写回复
用AI写文章
43 条回复
切换为时间正序
请发表友善的回复…
发表回复
healer_kx 2010-01-07
  • 打赏
  • 举报
回复
[Quote=引用 42 楼 yizhili 的回复:]
话说,现在的memcpy都不用考虑目标地址和源地址重叠的问题了吗?
前两天用的时候发生问题,才发现VC的memcpy也是不管的...
[/Quote]
不知道。。。但是更应该考虑memmove
yizhili 2010-01-07
  • 打赏
  • 举报
回复
话说,现在的memcpy都不用考虑目标地址和源地址重叠的问题了吗?
前两天用的时候发生问题,才发现VC的memcpy也是不管的...
healer_kx 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 40 楼 sammylan 的回复:]
case 0:也不会出现....
以下代码可以直接去掉了...
C/C++ codecase0:default:break;

不过有必要搞得那么复杂么?用常规的方法即可.

[/Quote]
嗯,是啊,。这次学习我意识到了,还是SSE是王道,自己写都是扯淡的。。。
SammyLan 2010-01-06
  • 打赏
  • 举报
回复
case 0:也不会出现....
以下代码可以直接去掉了...
case 0:
default:
break;


不过有必要搞得那么复杂么?用常规的方法即可.
healer_kx 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 36 楼 sammylan 的回复:]
不可能出现这种情况的啊case 8: *dc++ = *sc++;

[/Quote]
真是越来越崇拜sammy了。
haohaokingXP 2010-01-06
  • 打赏
  • 举报
回复
如果不考虑速度,稳健的话,还是按BYTE拷贝~,
haohaokingXP 2010-01-06
  • 打赏
  • 举报
回复
/* memcpy : copy memory */
void*
memcpy( void *dst, const void *src, size_t n )
{
register unsigned char *cdst, *csrc;

cdst = (unsigned char *)dst;
csrc = (unsigned char *)src;
while (n-- > 0) {
*cdst++ = *csrc++;
}

return dst;
}
SammyLan 2010-01-06
  • 打赏
  • 举报
回复
不可能出现这种情况的啊case 8: *dc++ = *sc++;
wangxipu 2010-01-06
  • 打赏
  • 举报
回复
找抽,简单的东西复杂化
lgccaa 2010-01-06
  • 打赏
  • 举报
回复
mark

学习草哥的学习精神
malu_1982 2010-01-06
  • 打赏
  • 举报
回复
jf
traceless 2010-01-06
  • 打赏
  • 举报
回复
这么多 很好
squallleonhart 2010-01-06
  • 打赏
  • 举报
回复

//test.cpp
//memcpy test
//编译命令:cl /EHsc /O2 test.cpp memcpy.cpp

namespace squall
{
namespace common
{
void* asmcpy1(void* dst, void const* src, unsigned int countbytes);
void* asmcpy2(void* dst, void const* src, unsigned int countbytes);
void* simcpy1(void* dst, void const* src, unsigned int countbytes);
void* simcpy2(void* dst, void const* src, unsigned int countbytes);
void* simcpy3(void* dst, void const* src, unsigned int countbytes);
void* simcpy4(void* dst, void const* src, unsigned int countbytes);
}
}


#include <iostream>
#include <cstdlib>
#include <ctime>
using std::endl;
using std::cout;

int main()
{
int const count = 1000000;
int const bufsize = 2048;
int const maxindex1 = 4;
int const maxindex2 = 4;
static char dstbuf[bufsize+maxindex2];
static char srcbuf[bufsize+maxindex2];
clock_t start, end, sum;

cout << "函数名称\t执行时间\tDst偏移\tSrc偏移\t数据量\t循环次数\n";

sum = 0;
for(int dstindex=0; dstindex<maxindex1; dstindex++)
{
for(int srcindex=0; srcindex<maxindex2; srcindex++)
{
char* dst = &dstbuf[dstindex];
char* src = &srcbuf[srcindex];

start = clock();
for(int i=0; i<count; i++) std::memcpy(dst, src, bufsize);
end = clock();
cout << "memcpy()\t" << end-start << "\t\t" << dstindex << '\t' << srcindex << '\t' << bufsize << '\t' << count << '\n';
sum += (end-start);
}
}
cout << "平均值\t\t" << static_cast<float>(sum)/(maxindex1*maxindex2) << endl << endl;

sum = 0;
for(int dstindex=0; dstindex<maxindex1; dstindex++)
{
for(int srcindex=0; srcindex<maxindex2; srcindex++)
{
char* dst = &dstbuf[dstindex];
char* src = &srcbuf[srcindex];

start = clock();
for(int i=0; i<count; i++) squall::common::asmcpy2(dst, src, bufsize);
end = clock();
cout << "asmcpy2()\t" << end-start << "\t\t" << dstindex << '\t' << srcindex << '\t' << bufsize << '\t' << count << '\n';
sum += (end-start);
}
}
cout << "平均值\t\t" << static_cast<float>(sum)/(maxindex1*maxindex2) << endl << endl;

sum = 0;
for(int dstindex=0; dstindex<maxindex1; dstindex++)
{
for(int srcindex=0; srcindex<maxindex2; srcindex++)
{
char* dst = &dstbuf[dstindex];
char* src = &srcbuf[srcindex];

start = clock();
for(int i=0; i<count; i++) squall::common::simcpy4(dst, src, bufsize);
end = clock();
cout << "simcpy4()\t" << end-start << "\t\t" << dstindex << '\t' << srcindex << '\t' << bufsize << '\t' << count << '\n';
sum += end-start;
}
}
cout << "平均值\t\t" << static_cast<float>(sum)/(maxindex1*maxindex2) << endl << endl;

sum = 0;
for(int dstindex=0; dstindex<maxindex1; dstindex++)
{
for(int srcindex=0; srcindex<maxindex2; srcindex++)
{
char* dst = &dstbuf[dstindex];
char* src = &srcbuf[srcindex];

start = clock();
for(int i=0; i<count; i++) squall::common::simcpy3(dst, src, bufsize);
end = clock();
cout << "simcpy3()\t" << end-start << "\t\t" << dstindex << '\t' << srcindex << '\t' << bufsize << '\t' << count << '\n';
sum += end-start;
}
}
cout << "平均值\t\t" << static_cast<float>(sum)/(maxindex1*maxindex2) << endl << endl;

sum = 0;
for(int dstindex=0; dstindex<maxindex1; dstindex++)
{
for(int srcindex=0; srcindex<maxindex2; srcindex++)
{
char* dst = &dstbuf[dstindex];
char* src = &srcbuf[srcindex];

start = clock();
for(int i=0; i<count; i++) squall::common::simcpy2(dst, src, bufsize);
end = clock();
cout << "simcpy2()\t" << end-start << "\t\t" << dstindex << '\t' << srcindex << '\t' << bufsize << '\t' << count << '\n';
sum += end-start;
}
}
cout << "平均值\t\t" << static_cast<float>(sum)/(maxindex1*maxindex2) << endl << endl;

sum = 0;
for(int dstindex=0; dstindex<maxindex1; dstindex++)
{
for(int srcindex=0; srcindex<maxindex2; srcindex++)
{
char* dst = &dstbuf[dstindex];
char* src = &srcbuf[srcindex];

start = clock();
for(int i=0; i<count; i++) squall::common::simcpy1(dst, src, bufsize);
end = clock();
cout << "simcpy1()\t" << end-start << "\t\t" << dstindex << '\t' << srcindex << '\t' << bufsize << '\t' << count << '\n';
sum += end-start;
}
}
cout << "平均值\t\t" << static_cast<float>(sum)/(maxindex1*maxindex2) << endl << endl;

return 0;
}



那个测试程序也发给你,可以详细对比下内存地址有偏移时各内存复制程序的性能差异
healer_kx 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 wshcdr 的回复:]
我能得多少分啊
[/Quote]

8分。。。因为8case~!
wshcdr 2010-01-06
  • 打赏
  • 举报
回复
我能得多少分啊
healer_kx 2010-01-06
  • 打赏
  • 举报
回复
谢谢各位,晚上结贴。
lajod 2010-01-06
  • 打赏
  • 举报
回复
路过
2010-01-06
  • 打赏
  • 举报
回复
话说当我看过 glibc 的 memcpy 实现以后,就决定不再轻易写这种东西了……

其实 x86 上面大批量写内存用 SSE 的 movnt 系列指令是最快的,其他各种方法(包括一次复制 64 位、32 位或者用 SSE2 复制 128 位,再或者用串操作等)在较老的机器上差别比较明显,在比较新的平台上差距已经基本被抹平了。
lvp1984 2010-01-06
  • 打赏
  • 举报
回复
菜鸟觉得是这样觉得:
这样底层的函数用c写不出来高效,每次取数的时候,首先将8字节内存源数据放入寄存器,再将数据付给目的内存.int本身就是个与平台有关的变量,64位redhat中int还是32位的,并没有充分利用64位寄存器,虽然在计算l的时候你的平台sizeof(int)是8.其次,后向++的效率和前向++效率哪个高? 这样的代码还是汇编来的实在,虽然64位汇编我也没写过
healer_kx 2010-01-06
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 wshcdr 的回复:]
该死的草,还是牛逼啊

除了不具备移植性和缺少 空指针检查外,一切都那么完美了,唉

PS:我最喜欢的是

case 8: *dc++ = *sc++;

[/Quote]
死dd,我在求学。。。 。。。再给点建设性意见呗。。。
加载更多回复(23)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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