CPU Throttling在Release模式下不再对Xcode起作用

mnemlml8  于 2023-06-24  发布在  其他
关注(0)|答案(1)|浏览(106)

我有一个对性能敏感的XCode C++项目,我正在使用CPU节流的技巧。我添加了以下代码:

// function to occupy a thread for an infinite amount of time
void coreEngager() {
    while (true) {}
}

// call it in the background thread
std::thread t1(coreEngager);

// call it once the work is done
t1.detach();

这个小技巧可以提高计算速度约50%,这在我的情况下非常重要。但是我最近发现了一个问题--如果我试图在发布模式下运行项目,这段代码会崩溃。coreEngager函数发生崩溃。我以前没有这个问题,现在在Linux和Windows上也没有这个问题。你能告诉我有什么变化或者如何在MacOS上使用CPU节流吗?

vql8enpb

vql8enpb1#

**我有时在基准测试时使用pause循环来保持CPU频率,但我不愿意在无限循环上浪费整个核心用于生产用途。**相反,调整CPU电源管理设置,或在安装指南中建议用户这样做。或者让你的程序(或单独的脚本)检查设置并推荐更改。

在C中,没有I/O或volatileatomic操作的无限循环是未定义的行为。编译器可以删除它们(https://eel.is/cdraft/intro.progress#1),clang会主动地这样做。它不会为coreEngager()函数发出asm指令,所以执行只福尔斯在二进制中的下一个函数中。
这个C规则旨在帮助编译器在循环条件不平凡时,这样他们可能会遇到证明循环终止的麻烦。
有趣的事实:ISO C有一个不同的规则,如果循环条件是一个常量表达式,如1,无限循环是定义良好的。但是IIRC,clang在这种情况下有一个bug,仍然应用C
规则。
要真正解决这个问题,请在循环中放入一个空的asm volatile("")语句,以使编译器满意,而不管目标是什么,而无需实际运行额外的指令。

#if defined(__x86_64__) || defined(__i386__)
#include <immintrin.h>
#define SPIN() _mm_pause()  // heat up the CPU less
#else
#define SPIN()  /**/
#endif

void coreEngager() {
    while (true) {
        asm("");       // counts as a volatile op for infinite-loop UB.
        SPIN();        // x86 pause or whatever
    }
}

Godbolt显示它可以按需要编译:

# clang16 -O3 for x86-64
coreEngager_buggy():         # zero asm instructions for your orig source!
coreEngager_fixed():
.LBB1_1:
        pause
        jmp     .LBB1_1
# clang16 -O3 for AArch64
coreEngager_buggy():
coreEngager_fixed():
.LBB1_1:
        b       .LBB1_1

如果有一个AArch 64等价于x86 pause,请使用它。可能没有,因为没有SMT AArch 64 CPU(多个逻辑核心共享一个物理核心),并且它们在自旋循环中没有内存顺序错误推测,因为它们没有x86的强有序内存模型。x86-compat内存模式下的M1除外;也许苹果有一个类似pause的指令?

我假设您正在为像Skylake这样的CPU进行调优,其中内存绑定代码可以让CPU降时钟,例如。在我的i7- 6700 k上,硬件P-state管理设置为balance_powerbalance_performance(与设置为完整performance不同),而不是3.7GHz。(Slowing down CPU Frequency by imposing memory stress
或者你有其他线程有时完全休眠,没有旋转线程,它们最初以空闲频率出现?(* 为什么这个延迟循环在几次迭代之后运行得更快,而没有睡眠?* )
相关内容:

相关问题