gpt4 book ai didi

c - 比使用 memset 更快的零内存方法?

转载 作者:太空狗 更新时间:2023-10-29 16:17:22 32 4
gpt4 key购买 nike

我了解到 memset(ptr, 0, nbytes) 确实很快,但是有没有更快的方法(至少在 x86 上)?

我假设 memset 使用 mov,但是在清零内存时大多数编译器使用 xor 因为它更快,对吗? edit1: 错误,正如 GregS 指出的那样,它只适用于寄存器。我在想什么?

我还请一个比我更了解汇编程序的人查看 stdlib,他告诉我在 x86 上 memset 没有充分利用 32 位宽寄存器。但是当时我很累,所以我不太确定我是否理解正确。

编辑2:我重新审视了这个问题并做了一些测试。这是我测试的内容:

    #include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <sys/time.h>

#define TIME(body) do { \
struct timeval t1, t2; double elapsed; \
gettimeofday(&t1, NULL); \
body \
gettimeofday(&t2, NULL); \
elapsed = (t2.tv_sec - t1.tv_sec) * 1000.0 + (t2.tv_usec - t1.tv_usec) / 1000.0; \
printf("%s\n --- %f ---\n", #body, elapsed); } while(0) \


#define SIZE 0x1000000

void zero_1(void* buff, size_t size)
{
size_t i;
char* foo = buff;
for (i = 0; i < size; i++)
foo[i] = 0;

}

/* I foolishly assume size_t has register width */
void zero_sizet(void* buff, size_t size)
{
size_t i;
char* bar;
size_t* foo = buff;
for (i = 0; i < size / sizeof(size_t); i++)
foo[i] = 0;

// fixes bug pointed out by tristopia
bar = (char*)buff + size - size % sizeof(size_t);
for (i = 0; i < size % sizeof(size_t); i++)
bar[i] = 0;
}

int main()
{
char* buffer = malloc(SIZE);
TIME(
memset(buffer, 0, SIZE);
);
TIME(
zero_1(buffer, SIZE);
);
TIME(
zero_sizet(buffer, SIZE);
);
return 0;
}

结果:

<罢工>zero_1 是最慢的,除了 -O3。 zero_sizet 是最快的,在 -O1、-O2 和 -O3 上具有大致相同的性能。 memset 总是比 zero_sizet 慢。 (-O3 的两倍慢)。一件有趣的事情是,在 -O3 时,zero_1 与 zero_sizet 一样快。然而,反汇编函数的指令数量大约是原来的四倍(我认为是循环展开造成的)。此外,我尝试进一步优化 zero_sizet,但编译器总是超过我,但这里并不奇怪。

现在 memset 获胜,之前的结果被 CPU 缓存扭曲了。 (所有测试都在 Linux 上运行)需要进一步测试。接下来我会试试汇编程序 :)

edit3:修复了测试代码中的bug,不影响测试结果

edit4: 在查看反汇编的 VS2010 C 运行时时,我注意到 memset 有一个针对零的 SSE 优化例程。很难击败它。

最佳答案

x86 是相当广泛的设备。

对于完全通用的 x86 目标,带有“rep movsd”的汇编 block 可以一次将零爆破到内存 32 位。尽量确保这项工作的大部分是 DWORD 对齐的。

对于带有 mmx 的芯片,带有 movq 的汇编循环一次可以达到 64 位。

您可能能够让 C/C++ 编译器使用 64 位写入和指向 long long 或 _m64 的指针。目标必须对齐 8 字节以获得最佳性能。

对于带有 sse 的芯片,movaps 很快,但前提是地址是 16 字节对齐的,所以使用 movsb 直到对齐,然后用 movaps 循环完成清除

Win32 有“ZeroMemory()”,但我忘了那是 memset 的宏,还是实际的“好”实现。

关于c - 比使用 memset 更快的零内存方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3654905/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com