关于memcpy的实现,单次复制Byte数

registercsdn 2020-07-04 08:05:24
https://www.geeksforgeeks.org/write-memcpy/
void myMemCpy(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;

// Copy contents of src[] to dest[]
for (int i=0; i<n; i++)
cdest[i] = csrc[i];
}
https://blog.51cto.com/12951882/1978164

都是一个char一个char的复制,不考虑src des重叠的情况的情况,为什么没有用到uint64_t or uint32_t?
整除64部分用64位,不整除部分用char,复制次数大大减少,速度上不应该有很大提升吗?

...全文
482 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
在真正的RTL实现中,memcpy这种基础函数实际上有多套实现,针对不同的数据规模和数据对齐情况
自信男孩 2020-07-06
  • 打赏
  • 举报
回复
是否需要考虑到字节序,如果按照楼主的减少循环次数,但是字节序如何保证?
千梦一生 2020-07-06
  • 打赏
  • 举报
回复
有道理,速度的话还是看寄存器。
当然,更重要的也是2l的说法。应用场景确实存在非整数倍的时候。
coo135 2020-07-06
  • 打赏
  • 举报
回复
都是一个char一个char的复制,不考虑src des重叠的情况的情况,为什么没有用到uint64_t or uint32_t? 整除64部分用64位,不整除部分用char,复制次数大大减少,速度上不应该有很大提升吗? ========================== 1:我想,myMemCpy是为了演示memcpy的算法,一个个char的复制,比较能说明问题。 2:如果使用uint64_t or uint32_t ,算法变得复杂,这样就失去重点了吧~。需要分成3段写:copy头部不对齐部分-->copy对齐部分-->copy尾部不对齐部分。 3:如你所说,优化后复制次数大大减少 ,速度上有极大的提升,库中的memcpy都有这样的优化。 4:像memcpy这么基础的函数,对性能影响极大,通常不会用C写的,如GCC、MSVC都是用汇编写的。 5:一次复制多少位,这和平台有关的。在例如在x86_64平台上,glibc、MSVC是按照128位对齐来复制的。 C语言写的memcpy实用价值不大,主要用来说明内存复制算法,因此在myMemCpy中使用64位优化,意义不是很大。
寻开心 2020-07-06
  • 打赏
  • 举报
回复
还是有区别的, 总线是分时共用的, 总线带宽对内存移动还是有影响的
一次移动多个字节肯定是比一次一个字节的效率高的

看汇编命令吧,内存之间移动指令: movsb, movsw,movsd
编译器最后优化成汇编去执行的

  • 打赏
  • 举报
回复
这个确实会有一定的优化效果的。
比如32位的电脑,一次复制4个字节。64位的电脑一次赋值8个字节。
都只占用一条CPU指令。

这个需要跟CPU,或者程序的位数有关了。
所以代码里面实现,会导致移植性变差,C/C++语言的移植性还不错。
所以这些功能,需要在编译器级别优化,而不是在代级别优化。
qybao 2020-07-04
  • 打赏
  • 举报
回复
我觉得不能光看表面上循环次数减少,还要看cpu操作指令差吧,也就是用uint64,每次cpu要使用用8个8位寄存器来操作数据,而使用char每次只需要操作1个8位寄存器,对寄存器的操作次数来说没什么差别(也就是从内存取数据到寄存器,再把寄存器的数据保存到内存,8个寄存器要操作8次,即表面上循环次数减少,实际上cpu操作次数未必少)。而从代码上来说,用uint64还要自己计算n/sizeof(uint64),即有几个整的unit64字节,和n%sizeof(uint64),即有几个非整的uint64字节,来分段处理,增加了cpu的操作指令(增加额外操作),所以未必就见得用uint64就能提高效率。
Simple-Soft 2020-07-04
  • 打赏
  • 举报
回复
引用 楼主 registercsdn的回复:
https://www.geeksforgeeks.org/write-memcpy/
void myMemCpy(void *dest, void *src, size_t n)
{
// Typecast src and dest addresses to (char *)
char *csrc = (char *)src;
char *cdest = (char *)dest;

// Copy contents of src[] to dest[]
for (int i=0; i<n; i++)
cdest[i] = csrc[i];
}
https://blog.51cto.com/12951882/1978164

都是一个char一个char的复制,不考虑src des重叠的情况的情况,为什么没有用到uint64_t or uint32_t?
整除64部分用64位,不整除部分用char,复制次数大大减少,速度上不应该有很大提升吗?
从算法的时间复杂度来讲,都是一样的,都是o(n),n/8和n在算法的复杂度来讲都是一样的。在实际使用过程中,赋值100次和赋值800次也没有太大区别
真相重于对错 2020-07-04
  • 打赏
  • 举报
回复
而且现在的编译器一般都做了优化,不再完全依赖于循环。
真相重于对错 2020-07-04
  • 打赏
  • 举报
回复
关键是内存的大小不一定是整数的倍数啊

69,337

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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