C++ 测试某个值是否在阈值范围内的最佳方法(性能方面)是什么?

C++ 测试某个值是否在阈值范围内的最佳方法(性能方面)是什么?,c++,performance,optimization,byte,C++,Performance,Optimization,Byte,也就是说,最快的测试方法是什么 if( a >= ( b - c > 0 ? b - c : 0 ) && a <= ( b + c < 255 ? b + c : 255 ) ) ... if(a>=(b-c>0?b-c:0)&& a对于a、b和c只需使用普通的ints,就可以将代码更改为更简单的代码 if (a >= b - c && a <= b + c) ... 在使用g++的x86上,为res2测

也就是说,最快的测试方法是什么

if( a >= ( b - c > 0 ? b - c : 0 ) &&
    a <= ( b + c < 255 ? b + c : 255 ) )

    ...
if(a>=(b-c>0?b-c:0)&&

a对于
a
b
c
只需使用普通的
int
s,就可以将代码更改为更简单的代码

if (a >= b - c && a <= b + c) ...
在使用g++的x86上,为
res2
测试生成的汇编代码只包含一条条件指令

下面循环的汇编代码是

void process(unsigned char *src, unsigned char *dst, int sz)
{
    for (int i=0; i<sz; i+=3)
    {
        unsigned char a = src[i];
        unsigned char b = src[i+1];
        unsigned char c = src[i+2];
        dst[i] = (unsigned(a - b + c) <= 2*c);
    }
}


.L3:
    movzbl  2(%ecx,%eax), %ebx    ; This loads c
    movzbl  (%ecx,%eax), %edx     ; This loads a
    movzbl  1(%ecx,%eax), %esi    ; This loads b
    leal    (%ebx,%edx), %edx     ; This computes a + c
    addl    %ebx, %ebx            ; This is c * 2
    subl    %esi, %edx            ; This is a - b + c
    cmpl    %ebx, %edx            ; Comparison
    setbe   (%edi,%eax)           ; Set 0/1 depending on result
    addl    $3, %eax              ; next group
    cmpl    %eax, 16(%ebp)        ; did we finish ?
    jg  .L3                   ; if not loop back for next
我现在太累了,无法尝试破译它(凌晨2:28)

无论如何,时间越长并不意味着必须越慢(乍一看,g++决定通过在本例中一次编写几个元素来展开循环)

正如我之前所说的,您应该使用实际计算和实际数据进行一些实际分析。请注意,如果需要真正的性能,最佳策略可能会因处理器而异


例如,Linux在引导过程中进行ae测试,以确定执行内核所需的特定计算的更快方式。变量太多(缓存大小/级别、ram速度、cpu时钟、芯片组、cpu类型…).

对于
a
b
c
只需使用普通的
int
s即可将代码更改为更简单的代码

if (a >= b - c && a <= b + c) ...
在使用g++的x86上,为
res2
测试生成的汇编代码只包含一条条件指令

下面循环的汇编代码是

void process(unsigned char *src, unsigned char *dst, int sz)
{
    for (int i=0; i<sz; i+=3)
    {
        unsigned char a = src[i];
        unsigned char b = src[i+1];
        unsigned char c = src[i+2];
        dst[i] = (unsigned(a - b + c) <= 2*c);
    }
}


.L3:
    movzbl  2(%ecx,%eax), %ebx    ; This loads c
    movzbl  (%ecx,%eax), %edx     ; This loads a
    movzbl  1(%ecx,%eax), %esi    ; This loads b
    leal    (%ebx,%edx), %edx     ; This computes a + c
    addl    %ebx, %ebx            ; This is c * 2
    subl    %esi, %edx            ; This is a - b + c
    cmpl    %ebx, %edx            ; Comparison
    setbe   (%edi,%eax)           ; Set 0/1 depending on result
    addl    $3, %eax              ; next group
    cmpl    %eax, 16(%ebp)        ; did we finish ?
    jg  .L3                   ; if not loop back for next
我现在太累了,无法尝试破译它(凌晨2:28)

无论如何,时间越长并不意味着必须越慢(乍一看,g++决定通过在本例中一次编写几个元素来展开循环)

正如我之前所说的,您应该使用实际计算和实际数据进行一些实际分析。请注意,如果需要真正的性能,最佳策略可能会因处理器而异


例如,Linux在引导过程中进行ae测试,以确定执行内核所需的特定计算的更快方式。变量太多(缓存大小/级别、ram速度、cpu时钟、芯片组、cpu类型…).

首先,让我们看看在没有各种溢流/溢流检查的情况下,您要检查什么:

a >= b - c
a <= b + c
subtract b from both:
a - b >= -c
a - b <= c
a>=b-c
a=-c

a-b b?a-b:b-a)首先,让我们看看在没有各种溢流/底流检查的情况下,您要检查什么:

a >= b - c
a <= b + c
subtract b from both:
a - b >= -c
a - b <= c
a>=b-c
a=-c

a-b-b?a-b:b-a)在另一个语句中嵌入三元运算符很少能提高性能:)


如果每个操作码都很重要,那么自己编写操作码——使用汇编程序。也可以考虑使用SIMD指令,如果可能的话。我也会对目标平台感兴趣。ARM汇编程序喜欢这种类型的比较,并且有操作码来加速这种类型的饱和数学。

在另一个语句中嵌入三元运算符很少能提高性能:)


如果每个操作码都很重要,那么自己编写操作码——使用汇编程序。也可以考虑使用SIMD指令,如果可能的话。我也会对目标平台感兴趣。ARM汇编器喜欢这种类型的比较,并且有操作码来加速这种类型的饱和数学。

它认为,以尽可能清晰的方式编写它,然后打开编译器优化器,将获得最佳性能。编译器在这类优化方面相当出色,并且在大多数情况下都会击败您(在最坏的情况下,它将与您并驾齐驱)

我倾向于:

int min = (b-c) > 0  ? (b-c) : 0 ;
int max = (b+c) < 255? (b+c) : 255;

if ((a >= min) && ( a<= max))
我的代码(汇编语言)

nightcracker代码(汇编语言)


它认为,通过以尽可能清晰的方式编写,然后打开编译器和优化器,您将获得最佳性能。编译器在这类优化方面相当出色,并且在大多数情况下都会击败您(在最坏的情况下,它将与您并驾齐驱)

我倾向于:

int min = (b-c) > 0  ? (b-c) : 0 ;
int max = (b+c) < 255? (b+c) : 255;

if ((a >= min) && ( a<= max))
我的代码(汇编语言)

nightcracker代码(汇编语言)



你是说a不我是说a在b的c单位之内,(a>=b-c和a通常c非常小,a和b可以是任何值。a和b代表R、G或b像素值,c是它们必须在“匹配”范围内的可接受阈值。我有这个阈值来解释着色非常轻微不同且仅以小像素值间隔关闭的等效图像。你是指a吗不我是说a在b的c单位之内,(a>=b-c和a通常c很小,a和b可以是任何东西。a和b代表R、G或b像素值,c是它们必须在“匹配”范围内的可接受阈值。我有这个阈值来解释相同的图像,这些图像的明暗程度略有不同,并且只有很小的像素值间隔。@Jason D:什么这是否意味着抢走某人的风头?英语不是我的母语。但我想它是非常积极的:)美丽。我知道有这样的东西潜伏着。谢谢。这仍然使用两个条件(一个用于三元运算符,一个用于与
c
进行比较)@6502:这些条件句的速度太快了!@Martin:除了a不能是负数,因为它是无符号的。@Jason D:抢别人的风头是什么意思?英语不是我的母语。但我想它是非常积极的:)很好。我知道有类似的东西潜伏着。谢谢。这仍然使用两个条件(一个用于三元运算符,另一个用于与
c
进行比较)@6502:而且这些条件句的速度非常快!@Martin:除了a不能是负数,因为它是无符号的。很抱歉Martin,但是你的偏好需要我20秒才能理解。我想我的
(a>b?a-b:b-a)有趣的方法是,使用冗长,这样编译器就可以准确地知道你在做什么,然后可以使用它的巧妙技巧做到最好。仍然使用如此多的操作让我感到紧张。我真的应该编译所有这些,看看哪一个有问题
abs(a - b) <= c
(a>b ? a-b : b-a) <= c
#include <iostream>

int main(int argc, char *argv[]) {  
    bool prevent_opti;
    for (int ai = 0; ai < 256; ++ai) {
        for (int bi = 0; bi < 256; ++bi) {
            for (int ci = 0; ci < 256; ++ci) {
                unsigned char a = ai;
                unsigned char b = bi;
                unsigned char c = ci;
                if ((a>b ? a-b : b-a) <= c) prevent_opti = true;
            }
        }
    }

    std::cout << prevent_opti << "\n";

    return 0;
}
int min = (b-c) > 0  ? (b-c) : 0 ;
int max = (b+c) < 255? (b+c) : 255;

if ((a >= min) && ( a<= max))
movl    %eax, %ecx
movl    %ebx, %eax
subl    %ecx, %eax
movl    $0, %edx
cmovs   %edx, %eax
cmpl    %eax, %r12d
jl  L13
leal    (%rcx,%rbx), %eax
cmpl    $255, %eax
movb    $-1, %dl
cmovg   %edx, %eax
cmpl    %eax, %r12d
jmp L13
movl    %eax, %ecx
movl    %ebx, %eax
subl    %ecx, %eax
movl    $0, %edx
cmovs   %edx, %eax
cmpl    %eax, %r12d
jl  L13
leal    (%rcx,%rbx), %eax
cmpl    $255, %eax
movb    $-1, %dl
cmovg   %edx, %eax
cmpl    %eax, %r12d
jg  L13
movl    %r12d, %edx
subl    %ebx, %edx
movl    %ebx, %ecx
subl    %r12d, %ecx
cmpl    %ebx, %r12d
cmovle  %ecx, %edx
cmpl    %eax, %edx
jg  L16