我在64位机器上优化memset的尝试比标准实现花费更多时间.有人可以解释一下原因吗?

前端之家收集整理的这篇文章主要介绍了我在64位机器上优化memset的尝试比标准实现花费更多时间.有人可以解释一下原因吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
(机器是x86 64位运行SL6)

我试图看看我是否可以在我的64位机器上优化memset.根据我的理解,memset逐字节地设置并设置值.我假设如果我以64位为单位,它会更快.但不知何故需要更多时间.有人可以看看我的代码并提出原因吗?

/* Code */
#include <stdio.h>
#include <time.h>
#include <stdint.h>
#include <string.h>

void memset8(unsigned char *dest,unsigned char val,uint32_t count)
{
    while (count--)
        *dest++ = val;
}
void memset32(uint32_t *dest,uint32_t val,uint32_t count)
{
    while (count--)
        *dest++ = val;
}
void
memset64(uint64_t *dest,uint64_t val,uint32_t count)
{
    while (count--)
        *dest++ = val;
}
#define CYCLES 1000000000
int main()
{
    clock_t start,end;
    double total;
    uint64_t loop;
    uint64_t val;

    /* memset 32 */
    start = clock();
    for (loop = 0; loop < CYCLES; loop++) {
        val = 0xDEADBEEFDEADBEEF;
        memset32((uint32_t*)&val,2);
    }
    end = clock();
    total = (double)(end-start)/CLOCKS_PER_SEC;
    printf("TiMetaken memset32 %g\n",total);

    /* memset 64 */
    start = clock();
    for (loop = 0; loop < CYCLES; loop++) {
        val = 0xDEADBEEFDEADBEEF;
        memset64(&val,1);
    }
    end = clock();
    total = (double)(end-start)/CLOCKS_PER_SEC;
    printf("TiMetaken memset64 %g\n",total);

    /* memset 8 */
    start = clock();
    for (loop = 0; loop < CYCLES; loop++) {
        val = 0xDEADBEEFDEADBEEF;
        memset8((unsigned char*)&val,8);
    }
    end = clock();
    total = (double)(end-start)/CLOCKS_PER_SEC;
    printf("TiMetaken memset8 %g\n",total);

    /* memset */
    start = clock();
    for (loop = 0; loop < CYCLES; loop++) {
        val = 0xDEADBEEFDEADBEEF;
        memset(&val,8);
    }
    end = clock();
    total = (double)(end-start)/CLOCKS_PER_SEC;
    printf("TiMetaken memset %g\n",total);

    printf("-----------------------------------------\n");
}

/*Result*/
TiMetaken memset32 12.46
TiMetaken memset64 7.57
TiMetaken memset8 37.12
TiMetaken memset 6.03
-----------------------------------------

看起来标准的memset比我的实现更优化.
我试着查看代码,到处都看到memset的实现与我为memset8所做的相同.当我使用memset8时,结果更像我期望的并且与memset非常不同.
有人可以建议我做错了什么吗?

解决方法

实际的memset实现通常在汇编时手动优化,并使用目标硬件上可用的最宽对齐写入.在x86_64上将至少有16B个商店(例如,movaps).它也可能利用预取(最近这种情况不太常见,因为大多数架构都有常规访问模式的良好自动流预取器),流媒体存储或专用指令(历史上的代表在x86上速度非常慢,但最近速度相当快微体系结构).你的实现不会做这些事情.系统实现速度更快不应该是非常令人惊讶的.

例如,考虑OS X 10.8中使用的implementation(已在10.9中取代).这是适度大小缓冲区的核心循环:

.align 4,0x90
1:  movdqa %xmm0,(%rdi,%rcx)
    movdqa %xmm0,16(%rdi,32(%rdi,48(%rdi,%rcx)
    addq   $64,%rcx
    jne    1b

当以16B /周期在Haswell以前的微体系结构上命中高速缓存时,该循环将使LSU饱和.基于像memset64这样的64位存储的实现不能超过8B /周期(甚至可能无法实现,具体取决于所讨论的微体系结构以及编译器是否展开循环).在Haswell上,使用AVX存储或rep stos的实现可以更快地实现32B /周期.

猜你在找的C&C++相关文章