在memcpy

时间:2016-02-05 23:11:52

标签: c alignment memcpy

我想编写一个memcpy代码,它逐字逐句而不是逐字节地提高速度。 (虽然我需要为最后或几个字节做一些逐字节复制)。所以我希望我的源和目标地址正确对齐。 我在glibc中看到了memcpy的实现 https://fossies.org/dox/glibc-2.22/string_2memcpy_8c_source.html 它只对目标地址进行对齐。但即使源地址没有正确对齐,也会导致总线错误(考虑在我的cpu中启用了对齐检查)我不确定如何使源和目标都正确对齐。因为如果我尝试通过逐字节复制几个字节来对齐源,它也会更改目标地址,因此首先正确对齐的目标地址现在可能无法正确对齐。 那么有没有办法对齐两者?请帮帮我。

void  memcpy(void  *dst,  void  *src,int  size)
{
   if(size >= 8)
   {
     while(size/8) /* code will give sigbus error if src = 0x10003 and dst = 0x100000 */ 
     {
       *((double*)dst)++  =  *((double*)src)++; 
        size  =  size  -  8;
     }
   }

   while(size--)
   {
     *((char*)dst)++  =  *((char*)src)++;
   }
}

2 个答案:

答案 0 :(得分:0)

...因此,首先正确对齐的目标地址现在可能无法正确对齐。那么有没有办法调整两者?

我发现这篇关于memcpy优化的文章,我相信它会讨论你想要做的事情......(见下面的代码示例链接)

modified-GNU算法:

void * memcpy(void * dst, void const * src, size_t len)
{
    long * plDst = (long *) dst;
    long const * plSrc = (long const *) src;

    if (!(src & 0xFFFFFFFC) && !(dst & 0xFFFFFFFC))
    {
        while (len >= 4)
    {
            *plDst++ = *plSrc++;
            len -= 4;
        }
    }

    char * pcDst = (char *) plDst;
    char const * pcDst = (char const *) plSrc;

    while (len--)
    {
        *pcDst++ = *pcSrc++;
    }

    return (dst);
} 

This 修改后的GNU算法的变体使用计算来调整地址错位。

答案 1 :(得分:0)

使用你包含的glibc memcpy代码,没有内存已经对齐就无法调用该函数。如果您按照我的方式编写自己的方式,memcpy有两种可能的对齐方式:

1)两个缓冲区从四字节边界偏移相同的量,或者两者都已经在四字节边界上。 (src % 4 == dst % 4)在这种情况下,逐个字节地复制前几个字节,然后使用目标地址的对齐就可以了。

2)缓冲区不在同一边界上。 (src % 4 != dst % 4)在这种情况下,为了从一个对齐复制到另一个对齐,一次一个字,处理器必须遵循类似下面的处理:

Load the new word
Split it into an upper half and lower half. 
Shift the upper half down
Shift the lower half up
Add the upper half the previous lower half. 
Store the combined copy to memory
Repeat

我不确定这会比逐字节复制更快。如果您的处理器架构允许它并且两个缓冲区在半字上对齐,则半字半字可能会更快,尽管我在支持半字加载/存储的架构上看到的大多数memcpy实现已经这样做了。