![](/img/trans.png)
[英]Are all of the CPUs that implement the AMD64 instruction set have the same instructions and registers?
[英]Why have AMD-CPUs such a silly PAUSE-timing
我已经为 C++ 开发了一个类似 Java 的监视器对象,并进行了一些改进。 主要的改进是不仅有一个用于锁定和解锁的自旋循环,还有用于等待事件的自旋循环。 在这种情况下,您不必锁定互斥锁,而是在 wait_poll 函数上提供一个谓词,并且代码反复尝试锁定互斥锁轮询,如果它可以锁定互斥锁,它会调用返回(或移动)一对的谓词布尔值和结果类型。
等待 kernel 中的信号量和/或事件对象 (Win32) 很容易花费 1.000 到 10.000 个时钟周期,即使调用立即返回也是如此,因为之前已经设置了信号量或事件。 因此,必须有一个与此等待间隔具有合理关系的旋转计数,fe 旋转 kernel 中花费的最小间隔的十分之一。
对于我的监视器对象,我从 glibc 中获取了自旋计数重新计算算法。 我也在使用暂停指令。 但是我发现在我的 CPU(TR 3900X)上暂停指令太快了。 平均约为 0.78ns。 在 Intel-CPU 上,大约 30ns 更合理。
这是代码:
#include <iostream>
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <immintrin.h>
using namespace std;
using namespace chrono;
int main( int argc, char **argv )
{
static uint64_t const PAUSE_ROUNDS = 1'000'000'000;
auto start = high_resolution_clock::now();
for( uint64_t i = PAUSE_ROUNDS; i; --i )
_mm_pause();
double ns = (int64_t)duration_cast<nanoseconds>( high_resolution_clock::now() - start ).count() / (double)PAUSE_ROUNDS;
cout << ns << endl;
}
为什么 AMD 采取了如此愚蠢的暂停时间? PAUSE 用于自旋等待循环,应该与缓存行内容翻转到不同核心并返回所需的时间非常匹配。
但是我发现在我的 CPU(TR 3900X)上暂停指令太快了。 平均约为 0.78ns。 在 Intel-CPU 上,大约 30ns 更合理。
pause
指令与时间没有任何关系,也不打算用作时间延迟。
pause
的目的是防止 CPU 浪费其资源(推测性地)并行执行循环的许多迭代; 这在超线程情况下特别有用,在这种情况下,核心中的不同逻辑处理器可以使用这些资源,但也有助于改善条件改变时退出循环所需的时间(因为你没有“N 次迭代”在条件改变之前排队的指令数)。
鉴于这种; 对于一个可能同时有 200 条指令在运行的极其复杂的 CPU, pause
本身可能会立即发生,但会在其唤醒时导致“200 个周期长”的管道气泡; 对于一个极其简单的 CPU(“按顺序”,没有推测性执行), pause
可能/应该实际上什么都不做(被视为nop
)。
PAUSE 用于自旋等待循环,应该与缓存行内容翻转到不同核心并返回所需的时间非常匹配。
不。假设缓存行在不同 CPU 的缓存中的“修改”state 中, pause
后的指令类似于“ cmp [lock],0
”,这会导致 CPU 尝试将缓存行放入“共享” " state。在pause
之后但在尝试将缓存行放入“共享”state 之前,CPU 应该无缘无故地浪费时间多长时间?
注意:如果您确实需要一个微小的时间延迟,那么您需要查看umwait
指令。 你不需要时间延迟 - 你想要一个超时(例如“ pause
旋转;直到rdtsc
说已经过了一定的时间)。为此我很想把它分成一个内部循环确实“ pause
并检查条件 N 次”然后执行“如果时间限制尚未到期则重试内部循环”的外部循环。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.