相关疑难解决方法(0)

为已知的更常见路径优化分支

请考虑以下代码:

void error_handling();
bool method_impl();

bool method()
{
    const bool res = method_impl();
    if (res == false) {
        error_handling();
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)

我知道当时method_impl()会返回true99.999%(是的,三位小数),但我的编译器没有.method()在时间消耗方面是部分关键.

  1. 我是否应该重写method()(并使其不太可读)以确保只有在method_impl()返回时才会发生跳转false?如果有,怎么样?
  2. 我应该让编译器为我做这项工作吗?
  3. 我应该让我的CPU的分支预测为我工作吗?

c c++ optimization compiler-optimization

6
推荐指数
3
解决办法
2227
查看次数

if 分支比 else 分支快吗?

我发现了这个非常漂亮的信息图,它对某些操作所使用的 CPU 周期进行了粗略估计。在学习时,我注意到一个条目“if的右分支”,我认为如果满足条件,该分支将采用“if”(编辑:正如评论中指出的“右”实际上意味着“正确预测的分支” )。这让我想知道 if 分支与 else 分支相比是否存在任何(即使是很小的)速度差异。

例如,比较以下非常简洁的代码:

演示

#include <cstdio>

volatile int a = 2;

int main()
{
    if (a > 5) {
        printf("a > 5!");
        a = 2;
    } else {
        printf("a <= 5!");
        a = 3;
    }
}
Run Code Online (Sandbox Code Playgroud)

它在 x86 64 位中生成此程序集:

.LC0:
        .string "a > 5!"
.LC1:
        .string "a <= 5!"
main:
        push    rcx
        mov     eax, DWORD PTR a[rip]
        cmp     eax, 5
        jle     .L2
        mov     edi, OFFSET FLAT:.LC0
        xor     eax, eax …
Run Code Online (Sandbox Code Playgroud)

c++ performance x86 assembly branch-prediction

6
推荐指数
1
解决办法
896
查看次数

我们代码中的函数会变慢吗?

当我们编译代码并执行它时,在汇编中,我们的代码被转换,函数以非顺序方式存储.因此,每次调用函数时,处理器都需要丢弃管道中的指令.这不会影响程序的性能吗?

PS:我没有考虑投入时间来开发没有功能的程序.纯粹在性能水平上.编译器是否有任何方法可以解决这个问题?

c language-agnostic x86 assembly pipeline

4
推荐指数
1
解决办法
176
查看次数

是否有可能帮助分支预测?

您是否可以有意识地以特定方式编写代码,以便分支预测器将选择大多数情况下的选项.例如,错误检查资源是否已加载.如果可能的话,你如何利用这个优势?

c c++ java branch-prediction

4
推荐指数
1
解决办法
299
查看次数

循环中复制与去重相同条件代码的性能

假设我有这样的代码,称之为版本 1:

while (some_condition) {
    // .. work that may trigger rare_condition ...

    if (rare_condition) {
        // .. rare work here ..
        continue;
    }

    // .. work that may trigger rare_condition ...

    if (rare_condition) {
        // .. rare work here ..
        continue;
    }

    // .. more work
}
Run Code Online (Sandbox Code Playgroud)

假设这两种情况下的“稀有作品”是相同的。我们可以等效地编写版本 2:

while (some_condition) {
    // .. work that may trigger rare_condition ...

    if (rare_condition) {
        goto rare_work;
    }

    // .. work that may trigger rare_condition ...

    if (rare_condition) {
        goto rare_work; …
Run Code Online (Sandbox Code Playgroud)

c optimization performance assembly x86-64

4
推荐指数
1
解决办法
134
查看次数

在不使用条件编译的情况下加速C程序

我们正在研究一种模型检查工具,它可以执行几十亿次搜索程序.我们有不同的搜索例程,目前使用预处理器指令进行选择.这不仅非常不方便,因为我们每次做出不同的选择时都需要重新编译,但也使代码难以阅读.现在是开始新版本的时候了,我们正在评估是否可以避免条件编译.

这是一个非常人为的例子,显示了效果:

/* program_define */

#include <stdio.h>
#include <stdlib.h>

#define skip 10

int main(int argc, char** argv) {
    int i, j;
    long result = 0;

    int limit = atoi(argv[1]);

    for (i = 0; i < 10000000; ++i) {
        for (j = 0; j < limit; ++j) {
            if (i + j % skip == 0) {
                continue;
            }
            result  += i + j;
        }
    }

    printf("%lu\n", result);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这里,变量skip是影响程序行为的值的示例.不幸的是,我们需要在每次需要新值时重新编译skip.

让我们看看该程序的另一个版本:

/* program_variable */

#include …
Run Code Online (Sandbox Code Playgroud)

c optimization conditional-compilation c-preprocessor

3
推荐指数
1
解决办法
1923
查看次数

我可以用我的代码改进分支预测吗?

这是一个对任何平台、语言或编译器都开放的天真的一般性问题。虽然我最好奇的是 Aarch64、C++、GCC。

当在依赖于 I/O 状态的程序流中编写不可避免的分支时(编译器无法预测),并且我知道一种状态比另一种状态更有可能,我如何向编译器表明这一点?

这是否更好

if(true == get(gpioVal))
    unlikelyFunction();
else
    likelyFunction();
Run Code Online (Sandbox Code Playgroud)

比这个?

if(true == get(gpioVal))
    likelyFunction(); // performance critical, fill prefetch caches from this branch
else
    unlikelyFunction(); // missed prediction not consequential on this branch
Run Code Online (Sandbox Code Playgroud)

如果通信协议使更有可能或临界值为真(高)或假(低),这是否有帮助?

c++ optimization gcc branch-prediction likely-unlikely

3
推荐指数
1
解决办法
2483
查看次数

为什么 C++ 标准库不使用可能/不可能的属性?

在 Visual Studio 中阅读标准库算法的实现时,他们根本不使用[[likely]]/属性。[[unlikely]]对我来说,应该使用的教科书示例[[unlikely]]是例如std::find_if(...),微软已经这样实现:

// Note that some noise are removed from the code
template <class _InIt, class _Pr>
_InIt find_if(_InIt _First, const _InIt _Last, _Pr _Pred) {
    for (; _First != _Last; ++_First) {
        if (_Pred(*_First)) {
            break;
        }
    }
    return _First;
}
Run Code Online (Sandbox Code Playgroud)

如前所述,find_if(...)这是 if 子句的 true 分支不太可能的教科书示例,因为大多数情况下它会在谓词验证为 true 之前迭代几个元素,因此 [[unlikely]] 将是一个优化机会。Microsoft 没有[[unlikely]]在这里使用该属性有什么原因吗?

c++ algorithm micro-optimization compiler-optimization likely-unlikely

3
推荐指数
1
解决办法
182
查看次数

x86装配 - 夹紧rax优化到[0 ..极限)

我正在编写一个简单的汇编程序,当然,它的目的是尽可能快.但是,位于最嵌套循环中的某个部分看起来并不"正确",我相信有可能提出更聪明,更快速的实现,甚至可能不使用条件跳转.代码实现了一个简单的事情:

if rax < 0 then rax := 0 else if rax >= r12 then rax := r12 - 1

这是我天真的实施:

cmp rax, 0
jge offsetXGE
   mov rax, 0
   jmp offsetXReady
offsetXGE:
   cmp rax, r12
   jl offsetXReady
   mov rax, r12
   dec rax
offsetXReady:
Run Code Online (Sandbox Code Playgroud)

任何想法都是受欢迎的,即使是那些使用MMX和一些掩盖技巧的想法.

编辑:回答评论中的一些问题 - 是的,我们可以假设r12> 0但rax可能是负数.

optimization x86 assembly nasm

2
推荐指数
1
解决办法
535
查看次数

Visual Studio 编译器在简单 if 语句的分支预测方面有多好?

下面是一些 C++ 伪代码作为示例:

bool importantFlag = false;
for (SomeObject obj : arr) {
    if (obj.someBool) {
        importantFlag = true;
    }
    obj.doSomethingUnrelated();
}
Run Code Online (Sandbox Code Playgroud)

显然,一旦 if 语句评估为 true 并运行内部代码,就没有理由再次执行检查,因为无论哪种方式结果都是相同的。编译器是否足够聪明,能够识别这一点,还是会在每次循环迭代中继续检查 if 语句,并可能再次将 importantFlag 冗余地分配为 true?如果循环迭代次数很大,并且无法跳出循环,则这可能会对性能产生显着影响。

我通常会忽略这些情况,只是将信心寄托在编译器上,但如果能确切地知道它如何处理这些情况,那就太好了。

c++ visual-studio branch-prediction

0
推荐指数
1
解决办法
363
查看次数