gpt4 book ai didi

c++ - RDTSCP 是否跨多核单调递增?

转载 作者:行者123 更新时间:2023-12-04 02:28:05 29 4
gpt4 key购买 nike

我很困惑 rdtscp在多核环境中单调递增。根据文档:__rdtscp , rdtscp似乎是基于处理器的指令,可以防止围绕调用重新排序指令。

The processor monotonically increments the time-stamp counter MSR every clock cycle and resets it to 0 whenever the processor is reset.

rdtscp肯定会在同一 CPU 内核上单调递增,但这是 rdtscp时间戳保证跨不同 CPU 内核的单调性?我相信没有这种绝对的保证。例如,
Thread on CPU core#0                   Thread on CPU core#1

unsigned int ui;
uint64_t t11 = __rdtscp(&ui);
uint64_t t12 = __rdtscp(&ui);
uint64_t t13 = __rdtscp(&ui);
unsigned int ui;
uint64_t t21 = __rdtscp(&ui);
uint64_t t22 = __rdtscp(&ui);
uint64_t t23 = __rdtscp(&ui);
以我的理解,我们可以有一个决定性的结论 t13 > t12 > t11 ,但我们不能保证 t21 > t13 .
我想写一个脚本来测试我的理解是否正确,但我不知道如何构建一个例子来验证我的假设。
// file name: rdtscptest.cpp
// g++ rdtscptest.cpp -g -lpthread -Wall -O0 -o run
#include <chrono>
#include <thread>
#include <iostream>
#include <string>
#include <string.h>
#include <vector>
#include <x86intrin.h>

using namespace std;

void test(int tid) {
std::this_thread::sleep_for (std::chrono::seconds (tid));
unsigned int ui;
uint64_t tid_unique_ = __rdtscp(&ui);
std::cout << "tid: " << tid << ", counter: " << tid_unique_ << ", ui: " << ui << std::endl;
std::this_thread::sleep_for (std::chrono::seconds (1));
}

int main() {
size_t trd_cnt = 3 ;
std::vector<std::thread> threads(trd_cnt);

for (size_t i=0; i< trd_cnt; i++) {
// three threads with tid: 0, 1, 2
// force different threads to run on different cpu cores
threads[i] = std::thread(test, i);
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
int rc = pthread_setaffinity_np(threads[i].native_handle(),
sizeof(cpu_set_t), &cpuset);
if (rc != 0) {
std::cout << "Error calling pthread_setaffinity_np, code: " << rc << "\n";
}
}

for (size_t i=0; i< trd_cnt; i++) {
threads[i].join() ;
}

return 0;
}
所以,这里有两个问题:
  • 我的理解正确与否?
  • 如何构建一个例子来验证它?

  • ==========更新,根据评论
    __rdtscp 将(总是?)在高级 CPU 上跨内核递增

    最佳答案

    在大多数系统上是的,如果您在线程之间创建同步以确保一个线程确实在另一个线程之后运行。否则所有赌注都将取消;在另一个线程之前启动一个线程并不能确保其代码首先执行。
    脚注 1:例如有一个旋转等待,直到它看到另一个完成的原子存储。或者使用互斥锁并运行 rdtscp在临界区,还有一个变量来记录另一个线程是否已经存在。

    在任何非古代(至少像 Core2 和更新版本)上,TSC 以恒定频率(“引用”)频率 滴答作响.见 this answer有关 constant_tsc 的链接和详细信息/nonstop_tsc CPU 功能,以及 TSC 未同步的可能性。
    大多数现代系统在实践中确实在内核之间同步了 TSC 我认为,感谢主板供应商确保即使在多插槽系统上,RESET 信号也能同时分配给所有内核。固件和操作系统软件小心不要搞砸。在单插槽系统上要容易得多,例如带有多核 CPU 的普通台式机,其中所有“额外”内核都在同一芯片上。
    但这是不保证 ,以及部分原因 rdtscp存在(带有处理器 ID 输出)是这种可能性(我认为当 RDTSCP 是新系统时,这在旧系统上可能更常见)。
    VM 甚至可以使用 CPU 功能来透明地偏移和扩展 TSC(具有硬件支持),在物理机之间迁移 VM,同时保持 TSC 的单调性和频率。不加选择地使用这些功能当然会产生不同步的 TSC,甚至会产生在不同内核上以不同频率运行的 TSC。

    TSC 是一个 64 位计数器,通常以 CPU 额定标签频率计数。在某些 CPU 上,这可能超过 ~4.2 GHz (2^32),因此在快速 CPU 上,高半部分每秒增加一次。 如果计算机已经“启动”超过 2^32 秒(几十年),或者如果 TSC 已被手动设置为具有较大偏移 ,则 TSC 理论上可以回绕。 .

    关于c++ - RDTSCP 是否跨多核单调递增?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65975629/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com