在memcpy中对齐源地址和目的地址。

问题描述 投票:4回答:2

我想写一个memcpy代码,它可以一个字一个字的复制,而不是一个字节一个字节的复制,以提高速度。(尽管我需要为最后一个或几个字节做一些逐字拷贝)。所以我希望我的源地址和目的地址能够正确对齐。我在glibc中看到了memcpy的实现。https:/fossies.orgdoxglibc-2.22string_2memcpy_8c_source.html。它只对目标地址进行对齐。但即使源地址没有正确对齐,也会导致总线错误(考虑到我的cpu中启用了Alignment Checking),我不知道如何使源地址和目的地址都正确对齐。因为如果我试图通过逐个字节复制几个字节来对齐源地址,它也会改变目标地址,所以一开始正确对齐的目标地址现在可能无法正确对齐。所以有什么方法可以同时对齐吗?请大家帮帮我。

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)++;
   }
}
c alignment memcpy
2个回答
1
投票

...所以一开始正确对齐的目标地址,现在可能无法正确对齐。那么有什么办法可以同时对齐两个地址吗?

我发现这篇文章 memcpy优化 其中我相信讨论了你想做的事情的长度... ...

修改后的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);
} 

0
投票

用你所包含的glibc memcpy代码 没有办法在内存没有被对齐的情况下调用这个函数。如果你要写你自己的,在我看来,memcpy有两种可能的对齐方式。

1) 两个缓冲区都从4字节的边界上偏移了相同的量 或者两个缓冲区都已经在4字节的边界上了。(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

我不确定这样做是否会比逐个字节复制更快。如果你的处理器架构允许,而且两个缓冲区都在半字上对齐,那么半字-半字的速度可能会更快,尽管我在支持半字loadstore的架构上看到的大多数memcpy实现已经做到了这一点。

© www.soinside.com 2019 - 2024. All rights reserved.