我有一个 C 程序,它创建两个线程(main 除外),T1 和 T2。 T1 执行一个发出操作 O1 的函数,T2 执行一个发出操作 O2 的函数。
void* f1() {
O1();
var = 0;
}
void* f2() {
O2();
var = 1;
}
int main(int argc, char **argv){
pthread_t t1, t2;
int var;
pthread_create(&t1, NULL, &f1, NULL);
pthread_create(&t2, NULL, &f2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("var = %d\n", var);
return 0;
}
t1
和 t2
分别分配给不同的物理内核。该程序的目标是在两个线程完成执行后通过检查 var 的值来检查哪个操作更快。这将要求 O1() 和 O2() 在两个内核上同时运行(或者在几个周期的数量级上存在非常微小的可容忍差异)。我怎样才能确保这一点?
编辑:根据 Peter Cordes 的建议,我修改了 f1()
和 f2()
以读取同步执行 O1( )
和 O2()
。
void* f1() {
t1 = rdtsc();
while(t1 != 0){
t1 = rdtsc();
}
printf("t1 = %d\n", t1);
O1();
var = 0;
}
void* f2() {
t2 = rdtsc();
while(t2 != 0){
t2 = rdtsc();
}
printf("t2 = %d\n", t2);
O2();
var = 1;
}
但是,t2
在控制台上打印的时间远远晚于 t1
的打印时间。我猜这表明 rdtsc
已在 f2()
中循环到 0,并且不会导致 O1()
的同步执行和O2()
。线程屏障没有提供我需要的同步粒度。
最佳答案
在大多数平台上,
f1
和 f2
在实践中肯定会被调用,但会有很小的延迟,但延迟取决于硬件、操作系统 (OS) 和特别是它的调度程序。理论上,无法保证这两个功能在所有平台上始终同时启动。事实上,操作系统调度程序可以自由地在同一核心上调度线程,即使您将线程绑定(bind)到核心,线程也可以随时被中断(例如,被更高优先级的任务中断)。此外,大多数现代处理器上的核心时钟并不强同步。话虽如此,在实践中,屏障显然足以使函数几乎同时运行(在大多数系统上,粒度接近几微秒,甚至可能更小)。 Pthread 提供了这样的功能(例如,请参见 pthread_barrier_init
和 pthread_barrier_wait
)。请注意,可能需要自旋等待以获得更好的精度(通常为 1-10 ns,就硬件而言可能稍短)。 AFAIK 不可能以比 x86 处理器几十个周期更好的精度来同步线程。这是因为现代处理器以并行和无序的方式运行指令,具有相当长的复杂管道,并且任何核心间同步都特别慢(通常是因为要采取很长的路径、缓存一致性协议(protocol)和基本原理)。物理定律)。
关于c - 在多个内核上同时运行两个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73094163/