Linux 如何启动两个CPU内核同时运行指令?

Linux 如何启动两个CPU内核同时运行指令?,linux,linux-kernel,x86-64,thread-synchronization,microbenchmark,Linux,Linux Kernel,X86 64,Thread Synchronization,Microbenchmark,例如,在X86中,2个CPU内核运行不同的软件线程。 目前,这两个线程需要同时在其CPU内核上运行。 有没有一种方法可以同步这两个CPU内核/线程,或者类似的方法,使它们在(几乎)相同的时间(指令级)开始运行?取决于您对“几乎”相同时间的定义,这在微体系结构上是一个非常困难的问题 即使是“运行”的定义也不够具体,如果你关心周期的计时。您的意思是从前端到故障后端的问题吗?执行?(分派到执行单元?或在不需要重播的情况下成功完成执行?)或退出 我倾向于使用Execute1,因为像rdtsc这样的指令会

例如,在X86中,2个CPU内核运行不同的软件线程。
目前,这两个线程需要同时在其CPU内核上运行。

有没有一种方法可以同步这两个CPU内核/线程,或者类似的方法,使它们在(几乎)相同的时间(指令级)开始运行?

取决于您对“几乎”相同时间的定义,这在微体系结构上是一个非常困难的问题

即使是“运行”的定义也不够具体,如果你关心周期的计时。您的意思是从前端到故障后端的问题吗?执行?(分派到执行单元?或在不需要重播的情况下成功完成执行?)或退出

我倾向于使用Execute1,因为像
rdtsc
这样的指令会对时间戳计数器进行采样。这是一个你可以记录的时间,然后比较

脚注1:在正确的道路上,而不是在错误猜测的阴影下,除非你也同意不到退休的死刑

但是,当您关心的指令执行时,如果这两个内核具有不同的ROB/RS状态,它们将不会继续锁定步骤。(像一些前Silvermont原子和早期的Xeon Phi:Knight’s Corner一样,订购的x86-64 CPU非常少。今天的x86-64 CPU都已经坏了,低功耗Silvermont系列之外的其他CPU也在积极地使用大型ROB+调度程序。)


x86 asm技巧: 我没有使用它,但是x86 asm
监视器
/
mwait
让两个CPU都监视并等待写入给定内存位置可能会起作用。我不知道唤醒有多同步。我猜睡眠越深,延迟的变化就越小

在写入之前中断的早期唤醒总是可能的。除非您禁用中断,否则您将无法在100%的时间内实现这一点;希望你只需要有一些合理的成功机会就可以实现它,并且能够事后判断你是否实现了它

(在最近的低功耗英特尔CPU(Tremont)上,可以使用用户空间可用的版本:
umonitor
/
umwait
。但在内核中,您可能只需使用
监视器
/
mwait

如果
umonitor
/
umwait
可用,则意味着您具有WAITPKG CPU功能,该功能还包括:如
暂停
,但要等到给定的TSC时间戳

在现代x86 CPU上,TSC通过硬件在所有内核之间同步,因此对多个内核使用相同的唤醒时间使这变得微不足道

否则,您可能会在
rdtsc
截止日期前旋转等待,在Skylake上最坏的情况下可能会在25个周期内

rdtsc
在Skylake()上每25个周期就有一个吞吐量,因此您预计每个线程平均会延迟12.5个周期离开自旋等待循环(+-12.5)。我假设两个线程的分支预测失误成本是相同的。这些是核心时钟周期,而不是rdtsc计数的参考周期。RDTSC通常接近最大非turbo时钟。有关来自C的RDTSC的更多信息,请参阅

请参阅,了解在
rdtsc
上旋转等待截止日期的asm函数。
您可以很容易地用C编写此函数


初始启动后保持同步: 在多核Xeon上,每个核都可以独立更改频率,您需要将CPU频率固定到某个值,可能max non turbo将是一个不错的选择。否则,由于内核的时钟速度不同,它们显然会立即去同步

在桌面上,您可能无论如何都想这样做,以防暂停时钟以更改CPU频率会造成问题


分支预测失误、缓存未命中、甚至ROB/RS初始状态的任何差异都可能导致严重的失同步


更重要的是,与在已经运行的任务中再运行一条指令相比,中断是巨大的,并且需要很长的时间。它甚至可以导致调度程序执行到另一个线程的上下文切换。或者为任务进行CPU迁移,显然要花费很多周期。

使用共享变量在两个线程之间传递基于
rdtsc
的截止日期。例如,设置一个截止日期,例如当前
rdtsc
值加10000

然后让两个线程在
rdtsc
上旋转,直到当前
rdtsc
值和阈值之间的间隙小于阈值
T
(T=100应该可以)。最后,使用最终间隙值(即deadline
rdtsc
值减去上次读取的
rdtsc
值)跳转到一系列相关的add指令中,以便add指令的数量等于间隙

这最后一步补偿了这样一个事实,即每个芯片通常不会与其
rdtsc
自旋环“同相”。例如,假设
rdtsc
读取的背对背吞吐量为30个周期,一个芯片可能会读取890、920、950等,而另一个芯片可能会读取880、910、940等,因此如果单独使用
rdtsc
,则会出现10或20个周期的错误。使用添加幻灯片补偿,如果截止日期为1000,阈值为100,则第一个线程将在
rdtsc==920
处触发并执行80个添加,而第二个线程将在
rdtsc==910
处触发并执行90个添加。原则上,这两个核心然后大致同步

一些注意事项:

  • 以上假设CPU频率等于标称
    rdtsc
    频率-如果不是这种情况,则在计算跳转到添加幻灯片的位置时,必须基于标称与真实频率比率应用补偿系数
  • 不要期望您的CPU说Synched for