在多线程程序中实现动态屏障的可能方法

时间:2011-08-01 17:59:20

标签: c++ c linux pthreads

我在一篇论文中读到了这个......

  

因此,我们的工具仅在执行时检查线程   在已知的安全点:内核入口,内核退出或确定   我们已经确定安全的内核中断了睡眠。   启动多线程fork的线程会创建一个屏障   在所有其他线程达到安全点之前等待它。一切都好   线程到达屏障,原始线程创建检查点,   然后让其他线程继续执行。

现在我的问题是,有人可以猜出作者正在谈论什么样的障碍。线程如何创建屏障并在其他线程中动态插入屏障?任何工作实例都将受到高度赞赏。

EDITED

请不要说使用 pthread_barrier_wait ,因为这不是问题。显然,作者有一个线程可以动态地将障碍插入到其他线程中。我想知道怎么做?

5 个答案:

答案 0 :(得分:4)

您询问的论文似乎是"Respec: Efficient Online Multiprocessor Replay via Speculation and External Determinism"。该文件提到:

  

我们修改了Linux内核以实现我们的技术。

  

因此,我们创建了一个名为多线程fork的新Linux原语,它创建了一个与其父级具有相同线程数的子进程。

所以当论文说明

  

Respec仅检查在一个已知安全点执行时的线程:内核条目,内核退出或内核中我们确定为安全的某些可中断睡眠。启动多线程分支的线程会创建一个屏障,等待所有其他线程到达安全点。一旦所有线程都到达屏障,原始线程就会创建检查点,然后让其他线程继续执行。

我认为他们对Linux内核进行的修改之中的逻辑是,正在记录的进程中的线程在到达其中一个“安全点”时将“进入”障碍(我还假设只有发布了一个“多线程分叉”来创建屏障)。由于这是在内核中发生的,因此很容易实现一个障碍 - 实际上并没有任何动态。修改后的内核在这些战略安全点上实施了障碍。

我还没读过这篇论文(只是略微浏览了一下)。我不完全清楚,如果一个或多个线程正在执行不需要长时间进入内核的工作,可能会发生什么 - 看起来系统依赖于线程到达那些显式安全点。所以线程不应该在CPU密集型循环中磨损太长时间(这对于绝大多数程序来说可能不是问题):

  

请注意,由于我们的屏障实施,时期的实际执行时间可能比时期间隔长;在所有线程都到达屏障之前,不能使用检查点。

答案 1 :(得分:2)

考虑到你的问题用linux和pthreads标记,我只能想象它指的是pthread障碍:

以下是一个例子:

#include <pthread.h>
#include <stdio.h>

pthread_barrier_t bar;
pthread_t  th;

void* function(void*)
{  
    printf("Second thread before the barrier\n");
    pthread_barrier_wait(&bar);
    printf("Second thread after the barrier\n");
    return NULL;
}

int main()
{
    printf("Main thread is beginning\n");
    pthread_barrier_init(&bar, NULL, 2);
    pthread_create(&th, NULL, function, NULL); 
    pthread_barrier_wait(&bar);
    printf("Main thread has passed the barrier\n");
    pthread_join(&th,NULL);
    pthread_barrier_destroy(&bar);
    return 0;
}

答案 2 :(得分:0)

屏障是fairly standard synchronization primitive

从基本的角度来说,一旦进入障碍,每个线程都会被阻塞,直到所有相关线程都到达障碍,然后全部被释放。

我知道你在询问C / C ++,但是看看Java CyclicBarrier,因为这个概念很好地解释了。

既然您在询问pthreads,请查看pthread_barrier_init等。

修改

  

但在这种情况下,一个线程似乎动态地插入障碍   其他线程。怎么样?

如果没有某种背景(例如您正在阅读的论文),很难回答这个问题。

您引用的摘录给人的印象是,这是对某些低级工具的描述,要么插入在某些事件上执行的钩子(可能在相关线程的上下文中),要么实际在内核中运行模式。无论哪种方式,它都可以做到它所能做的事情,这一点也就不足为奇了。

在我看来,没有人在谈论用户线程动态地将障碍插入另一个用户线程。

希望我在猜测背景时不会太离谱。

答案 3 :(得分:-1)

简单:使用pthread_barrier_wait pthread API调用。

有关详细信息,请参见手册页:http://linux.die.net/man/3/pthread_barrier_wait

答案 4 :(得分:-1)

OS线程障碍只不过是内存中的某种状态。如果您可以在线程之间共享该状态(通过正确初始化线程),则线程可以使用该障碍。

基本上主线程是:

CreateAllThreads(&barrier);
StartAllThreads();
EnterBarrier(&barrier);

所有其他线程:

RuntimeInitialize();
EnterBarrier(&barrier);

以上只是一个非常粗糙的伪代码,仅供说明之用。