想要使用ASM进行快速8字节对齐的数组复制而不是memmove

时间:2011-10-22 13:57:11

标签: c assembly x86

我有一个结构数组,大小在8字节的边界内。我需要在数组本身的大块中移动数据,所以我一直在使用memmove()。它有效,但速度很慢。我认为编译器没有优化函数来复制4或8个字节,因此延迟。

我宁愿做的是使用int32_t或int64_t vars强制复制。这样,我可以将memcpy复制4或8个字节,从而加快速度。这将正常工作,因为我的结构总是大小为8字节边界。

我无法想出一种在C中强制执行此操作的方法。我尝试使用内联汇编来完成它,但我不知道如何将操作数指向特定的数组元素。例如,如果我的ASM语句一次复制4个字节,我需要将数组前进4个字节。我不知道该怎么做。这就是我的想法:

//here's our 2048 byte struct
typedef struct {
    filename[1024];
    description[1024];
} RECORD;

//total number of rows, or elements
int row_count = 0;

//create initial record
RECORD *record = (RECORD*)malloc(sizeof(RECORD));

//insert some stuff
strcpy(record->filename,"filename.txt");
strcpy(record->description,"Description of file");

//increment our row count
row_count++;

//now let's add a row
record = (RECORD*)realloc(record,sizeof(RECORD)*(row_count+1));

//duplicate first record
//copy first 4 bytes from "record" to the newly appended row
//obviously this would be a loop copying 4 bytes at a time
//up to the the size of the row, which is 2048 bytes.
__asm__("movl (%1), %%eax; \n\t"
    "movl %%eax, (%0); \n\t"
    : "=r"(record+row_count)    //output
    :  "r"(record+0)            //input
    : "%eax" );                 //list of registers used

//Don't work. :-(

1 个答案:

答案 0 :(得分:4)

@Vlad指出,memmove&amp; memcpy通常是高度优化的,现在它们通常使用SIMD实现大块,这意味着您应该在花时间优化您认为成为瓶颈的时候之前对代码进行分析。< / p>

关于你的实际问题: 你的副本中没有任何循环,但是,最好一次使用REP MOVSD这样的内容,一次使用4个字节,或者一次使用REP MOVSQ x64上的8个字节。但是,看到你的数据是8字节对齐的,你甚至可以使用MMX通过MOVQ进行复制,一次只能做64位。

当有重叠和其他有趣的角落情况时,这会变得有点复杂,但从它的声音你不应该/需要,所以实际上,最好的方法可能是最天真的(这只是副本,如果你不需要memmove)的其他语义,它将加快速度:

void MyMemCopy(void* pSrc, void* pDst, int nElements)
{
    int64_t* s = (int64_t*)pSrc;
    int64_t* d = (int64_t*)pDst;
    while(nElements--)
        *d++ = *s++;
}

现在编译器可以以最佳方式自由地优化它,无论是内联还是展开等,并且您没有ASM的可移植性问题