memcpy()函数实现

1.为什么会写memcpy

笔试中遇到过一道笔试题,题目要求实现一个my_memcpy函数。函数原型:void * my_memcpy(void *dst, const void *src, int n);

memcpy()函数实现

之前使用的内存拷贝函数是标准库memcpy函数,拿来就用。当你自己在实现过程中,了解的越多,实现起来就越麻烦。

2.按字节(Byte)拷贝实现的memcpy

  • 不考虑写覆盖,简单粗暴:
void* my_memcpy_byte(void* dst, const void* src, size_t n) {
    // Copies n bytes from src to dst
     
    // Since we cannot dereference a void* ptr,
    // we first typecast it to a char* ptr
    // and then do the copying byte by byte,
    // since a char* ptr references a single byte
    char* char_dst = (char*) dst;
    char* char_src = (char*) src;
 
    for (int i=0; i<n; i++) {
        *char_dst++ = *char_src++;
    }
 
    return dst;
}
  • 考虑写覆盖:
void *my_memcpy_byte(void *dst, const void *src, int n)
{
    if (dst == NULL || src == NULL || n <= 0)
        return NULL;

    char * pdst = (char *)dst;
    char * psrc = (char *)src;

    if (pdst > psrc && pdst < psrc + n)
    {
        pdst = pdst + n - 1;
        psrc = psrc + n - 1;
        while (n--)
            *pdst-- = *psrc--;
    }
    else
    {
        while (n--)
            *pdst++ = *psrc++;
    }
    return dst;
}    
//*pdst-- = *psrc--;  查了下运算符优先级(*,--)优先级相同,从右向左结合,psrc--是先使用,后减减    
//等价于*pdst = *psrc;psrc--;pdst--;

 

3.按4字节拷贝实现的memcpy

 

 void *my_memcpy(void *dst, const void *src, int n)
 {
 if (dst == NULL || src == NULL || n <= 0)
 return NULL;

 int * pdst = (int *)dst;
 int * psrc = (int *)src;
 char *tmp1 = NULL;
 char *tmp2 = NULL;
 int c1 = n / 4;
 int c2 = n % 4;
 
 /*if (pdst > psrc && pdst < psrc + n) 这样判断有问题*/
 if (pdst > psrc && pdst < (char *)psrc + n)
 {
 tmp1 = (char *)pdst + n - 1;
 tmp2 = (char *)psrc + n - 1;
 while(c2--)
 *tmp1-- = *tmp2--;
 /*这样有问题,忘记字节偏移
 pdst = (int *)tmp1;
 psrc = (int *)tmp2;
 */
 tmp1++;tmp2++;
 pdst = (int *)tmp1;
 psrc = (int *)tmp2;
 pdst--;psrc--;
 while (c1--)
 *pdst-- = *psrc--;
 }
 else
 {
 while (c1--)
 *pdst++ = *psrc++;3536 tmp1 = (char *)pdst;
 tmp2 = (char *)psrc;
 while (c2--)
 *tmp1++ = *tmp2++;
 }
 return dst;
}      

//备注:void *dst, const void *src这两个参数是需要按4字节对齐的,如果本身不是4字节对齐,按4字节拷贝效率也会变低。

这里还是考虑了写覆盖的代码。对比按字节拷贝,拷贝速度是提高不少。

以上是针对笔试过程中写memcpy。

4.如何优化memcpy

高性能的memcpy与很多因数相关,与平台,处理器,编译器,具体拷贝情形等相关。

VS2017中对C库的memcpy进行优化,glibc对memcpy也有优化

参考:怎样写出一个更快的 memset/memcpy ?

5.是否需要考虑内存对齐拷贝?

内存读写效率影响之一:内存对齐

参考:1.浅谈CPU内存访问要求对齐的原因     2.解析内存对齐

如果src,dst的地址是不对齐的,读写效率变低。

通过代码实现不对齐的拷贝,memcpy的实现会变得复杂,反而影响拷贝效率。

这种不对齐情况我们可以预先避免,因为编译器在给我们分配空间时是按照内存对齐进行分配的

6.根据拷贝数据大小进行优化

1.多次调用memcpy,而每次拷贝数据大小Kb下的小拷贝

  这种情况下尽量减少分支预测,代码精简。

2.拷贝Mb的memcpy实现

  这种情况影响拷贝效率主要在寻址上。

参考:闲着没事测了一下memcpy

 

参考:

实现memcpy()函数及过程总结

 

  

上一篇:内核ram外的/ dev / mem的memcpy性能


下一篇:memcpy函数的用法以及实现一个memcpy函数