求减法结果平方的最快方法?

dev*_*l05 1 c

我需要对减法结果进行平方,并且需要速度快。

我已经确定了一些可能的方法,但我想听听优点和缺点

unsigned int a = 5;
unsigned int b = 7;


/* Approach 1a */
unsigned int c  = (a - b) * (a - b);

/* Approach 1b */
int d = (a - b);
unsigned int e = d * d;


/* Approach 2a */
unsigned int f = abs(a - b) * abs(a - b);

/* Approach 2b */
unsigned int g = abs((a - b) * (a - b));

/* Approach 2c */
unsigned int h = abs(a - b);
unsigned int i = h * h;


/* Approach 3a */
unsigned int j = (a > b) ? ((a - b) * (a - b)) : ((b - a) * (b - a))
Run Code Online (Sandbox Code Playgroud)

我不确定如何确保编译器不会优化的随机负数,所以我只写了一般概念。我确信只需查看一些解决方案就可以将它们挑出为(次)最优的。

Mik*_*CAT 6

作为一般规则,您应该避免分支来制作快速程序。因此,使用额外的abs条件运算符并不好。

还要相信你的编译器会进行优化。

我使用带有选项的 x86-64 gcc 13.1在Compiler Explorer上测试了代码的稍微修改版本-O2

#include <stdlib.h>

unsigned int  hoge(unsigned int a, unsigned int b) {
    /* Approach 1a */
    unsigned int c  = (a - b) * (a - b);

    /* Approach 1b */
    int d = (a - b);
    unsigned int e = d * d;


    /* Approach 2a */
    unsigned int f = abs(a - b) * abs(a - b);

    /* Approach 2b */
    unsigned int g = abs((a - b) * (a - b));

    /* Approach 2c */
    unsigned int h = abs(a - b);
    unsigned int i = h * h;


    /* Approach 3a */
    unsigned int j = (a > b) ? ((a - b) * (a - b)) : ((b - a) * (b - a));

    /* test c, e, f, g, i, j here */
    return c;
}
Run Code Online (Sandbox Code Playgroud)

在此设置中,未使用的方法将被优化掉。

返回cef、 和g会得到相同的结果:

hoge:
        movl    %edi, %eax
        subl    %esi, %eax
        imull   %eax, %eax
        ret
Run Code Online (Sandbox Code Playgroud)

返回的i结果是:

hoge:
        subl    %esi, %edi
        movl    %edi, %eax
        negl    %eax
        cmovs   %edi, %eax
        imull   %eax, %eax
        ret
Run Code Online (Sandbox Code Playgroud)

返回的j结果是:

hoge:
        cmpl    %edi, %esi
        jnb     .L2
        movl    %edi, %eax
        subl    %esi, %eax
        imull   %eax, %eax
        ret
.L2:
        movl    %esi, %eax
        subl    %edi, %eax
        imull   %eax, %eax
        ret
Run Code Online (Sandbox Code Playgroud)

从这个测试中,我们可以说方法1a、1b、2a、2b应该具有相同的性能,而方法2c和3a的性能会比它们差。

请注意,结果应取决于编译器、选项和目标机器。

我认为方法 1b 是最好的方法,因为它简单并且a - b不需要手动重复计算。

如果您想要更快的操作,您可以选择使用 SIMD 操作或 GPU。