x86 上的 C 64 位循环性能

标签 c performance algorithm 64-bit

对于某些使用原始套接字的 IPv4 ICMP 处理代码,我需要一个 Internet 校验和函数(一个的补码校验和),但我偶然发现了我无法在 64 位 Intel 处理器(使用 gcc 4.8.2)上解释的行为。我想知道是否有人可以阐明它。

我使用 32 位累加器实现了第一个校验和函数并执行 16 位求和。然后我使用 64 位累加器和 32 位求和实现了相同的方法,认为更少的求和会导致更快的执行。结果是第一个实现的运行速度是第二个实现的两倍(使用 O3 优化)。我只是想不通为什么...

下面的代码实际上并没有执行准确的校验和(我已经简化了它)但说明了问题。两者都编译为 64 位,在 64 位 native 平台上运行(LP64:short 16 位,int 32 位,long 64 位,指针 64 位)。

  1. 32 位累加器和 16 位求和

    unsigned short
    cksum_16_le(unsigned char* data, size_t size)
    {
        unsigned short word;
        unsigned int sum = 0;
        unsigned int i;
    
        for(i = 0; i < size - 1; i += 2)
            sum += *((unsigned short*) (data + i));
    
        sum = (sum & 0xffff) + (sum >> 16);
        sum = (sum & 0xffff) + (sum >> 16);
    
        return ~sum;
    }
    

50,000 个函数调用相同的 10k 数据:~1.1 秒。

  1. 64 位累加器和 32 位求和

    unsigned short
    cksum_32_le(unsigned char* data, size_t size)
    {
        unsigned long word;
        unsigned long sum = 0;
        unsigned int i;
    
        for(i = 0; i < size - 3; i += 4)
            sum += *((unsigned int*) (data + i));
    
        sum = (sum & 0xffffffff) + (sum >> 32);
        sum = (sum & 0xffffffff) + (sum >> 32);
        sum = (sum & 0xffff) + (sum >> 16);
        sum = (sum & 0xffff) + (sum >> 16);
    
        return ~sum;
    }
    

50,000 个函数调用相同的 10k 数据:~2.2 秒。

更新:

看来是硬件问题。运行内存诊断显示偶尔出现总线奇偶校验错误(不确定为什么这对 32 位版本的影响比对 16 位版本的影响更大,但你知道了)。代码在其他服务器上按预期运行。将在接下来的几个小时内删除该问题(与硬件相关,它不再特别有用)。

最后更新:

有趣的是,将 for 循环替换为 while 循环并使用 O3 优化进行编译(如下所示,针对 64 位累加器的情况)同时获得 32 位和 64 -bit 累加器案例以相同的速度运行。这是因为编译器执行了一些循环展开(奇怪的是,它没有展开 for 循环)并使用 mmx 寄存器执行求和...

uint64_t sum = 0;
const uint32_t* dptr = (const uint32_t*) data;

while (size > 3)
{
    sum += (uint32_t) *dptr++;
    size -= 4;
}

最佳答案

我之前遇到过类似的问题;我在我们的任何一个代码中都找不到任何问题。但对我有用的是更改编译器。

我的猜测是 GCC 正在编写已弃用的程序集。

如果您可以反编译您的应用程序,我们可以更清楚地了解这个问题,但这里没有足够的信息继续进行。

当我反编译我的代码时,我发现它多次重写了整个方法。但这可能只适合我。

希望这对您有所帮助,几乎没有任何关于此的信息。

如果我不得不猜测我会同意 Learner 的观点,我很确定反编译代码会指向 for 循环。我对这个问题很感兴趣,所以请回复。

关于x86 上的 C 64 位循环性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21654207/

相关文章:

android - 当同时使用两种语言时,TextToSpeech 队列性能不佳

c - 搜索元素的有效方法

c - C 中的 unsigned char 与 char — 字符串比较

c - 如何在一行中从 cmd 运行应用程序

performance - Excel VBA : Writing an array to cells is very slow

java - 这是打印二维数组最快的方法吗?

确定 Y 轴标签和位置的算法?

c++ - 沿路径生成 3d 圆柱体的算法

c - 相同数的最长序列&最长序列有多少个(无数组)

c - 经典书籍 "The C Programming Language"中1.9章的示例代码是否有错误?