2

假设我正在运行 N 个线程。每个线程都需要与下一个和上一个线程同步。

    for (i = 0 ; i < NITER; i++){
      do_something ();
      sync_with_neighbours (tId - 1, tId + 1);
    }

我需要以最有效的方式实现同​​步。Pthread 屏障效率不高,因为这样每个线程都会等待最慢的线程到达屏障。

欢迎任何想法

编辑:

不,我们不必等待线程 0:

如果这两个相邻线程“i + 1”和“i - 1”准备就绪,则线程“i”将运行。

假设我们在 T 时刻在这种情况下运行 6 个线程:

  • th0:待定(运行 iter = m )
  • th1:待定(运行 iter = m )
  • th2:准备好(等待)
  • th3:准备好(等待)
  • th4:准备好(等待)
  • th5:待定(运行 iter = m )

T + 1 的情况将是:

  • th0:待定(运行 iter = m )
  • th1:待定(运行 iter = m )
  • th2:准备好(等待)
  • th3:运行 iter = m + 1
  • th4:准备好(等待)
  • th5:待定(运行 iter = m )

如您所见,每个人都无需等待 Th0

4

3 回答 3

3

我假设(按照您的示例)您的意思是同步不是真正的会合,而是交叉信号。因此,如果任何线程从每个邻居那里获得空闲信号,它都可以运行。为此,您可以使用信号量,每个线程一个。同步部分如下所示:

   UP(left_sem)
   UP(right_sem)
   DOWN(own_sem,2)

(第一个和最后一个线程没有左右邻居,分别。因此,它们只需要一个简单的DOWN

关于实现:经典的 System V 信号量似乎是合适的,因为 System V 系统调用已经处理了信号量数组,因此您只需要做一些索引。但是,每种信号量都应该足够了。

于 2012-12-01T20:59:19.510 回答
1

只是为了好玩-您可以查看我的游戏生活编码示例-

http://parallel.cc/cgi-bin/bfx.cgi/test_cases.html

但是由于您没有 ParC,并且被 pThreads 卡住了,所以这有点棘手。最快的同步方法通常是使用一个简单的信号量机制,其中(p)线程保持热状态并且只读取一个内存位置直到它改变(例如等待它变为非零)。

要记住的事情:

如果您将数据和信号量分开,使得通过内存子系统的写入不是原子的和/或有序的东西可能不起作用(有时),因此至少确保所有内容都在同一缓存行上(如果可能),否则校验和您的数据所以接收方知道它有一套完整的数据。

注意 1:我假设您的意思是“速度”而不是“效率”,并且您拥有与线程一样多的内核。

注 2:pThreads 源于操作系统级别的多线程(粗略),只是在这个级别很烂(精细)。

于 2012-12-03T09:15:30.013 回答
0

一种方法可以通过使用 OpenMP 库(这个库也使用 pthreads)来传递,并使用有序子句

在执行带有有序子句的 for 或并行 for 构造时,有序构造严格按照它们在循环的顺序执行中的执行顺序执行。

如果我正确理解您的问题,线程 8 必须与 7 和 9 同步,但 7 必须与 6 和 8 同步,依此类推,所以实际上每个线程都必须等待线程 0。一旦线程 0 准备好,线程 1 也可以准备好,依此类推。因此,看起来每个有序子句都可能有用。

于 2012-12-01T04:02:03.427 回答