【问题标题】:Multi-threaded Flood Fill多线程洪水填充
【发布时间】:2015-02-26 18:09:17
【问题描述】:

我正在尝试将现有的单线程洪水填充算法转换为多线程算法。

输入: - 二维位数组及其暗淡 - 填充应开始的 xy 坐标

输出: - 具有更新位的相同二维位数组

问题: - 当时只有 1 个线程可以写入数组中给定的 64 位(8x8 像素),也没有其他线程可以在写入时读取这个 64 位块

我已经开始使用队列方法和线程池,所以一旦线程完成它的工作,它就可以从队列中获取另一个任务。

您将如何组织符合“问题”声明的线程同步?

主要问题是如何为给定的内存块分配读/写储物柜?

【问题讨论】:

  • Flood fill 从来没有让我觉得适合多线程。下一步行动过于依赖先前的结果。祝你好运。
  • 应该从多个坐标开始,还是从单个 (x,y) 坐标开始?
  • @didierc,只是单个 x,y。它应该快速填充到需要填充递归的许多点。
  • 您可以从起点将区域划分为象限,并让 4 个线程工作,每个线程一个。
  • 事实上,您可能应该重新考虑将新坐标推送到队列中的顺序,以便对坐标进行分组,以帮助线程不踩到彼此的脚趾.

标签: multithreading algorithm flood-fill


【解决方案1】:

通常您希望尽可能粗略地划分数据并尽量减少线程之间的通信。通信包括共享数据结构,甚至是无锁的。尤其是那些有写权限的共享变量。

高于一般“粗略”策略可避免阻止扩展的常见陷阱(例如 false sharing)。

至于你的具体问题,我不得不承认,我对洪水填充算法并不熟悉,所以我不能立即勾勒出粗略的方法。

但是,如果粗略的方法不可行并且需要锁定单个单元格的策略,lock striping 在这种情况下可能是值得研究的方法。

无锁实现是另一种可能性。如果另一个线程在同一个 8x8 像素 64 位块中写入,则可能使用比较和交换类型的操作来执行写入(VS 上的InterlockedCompareExchange64)结合重试逻辑。

完全放松读锁定是可能的。如果 2 个线程最终绘制相同的像素,可能只会浪费一些周期,但不会破坏结果。

无锁实现could be several times faster

如果您使用 Java,Java Concurrency in Practice by Goetz 是一本关于锁条带化之类的好书。

【讨论】:

  • 感谢您的反馈。因此,在您看来,由于缓存架构,这将扼杀并行处理,或者您是在暗示如何不陷入缓存行限制问题?
  • 我会尝试继续添加我的答案。我同时在看一个 1 岁的孩子:D
  • 我只是想警告那些令人讨厌的难以发现的问题,这些问题可能会破坏原本聪明的并行化策略。我可能会尝试改写我的帖子...
  • 谢谢,我在 c++ 和 win32 同步对象 + 用于线程管理的互锁操作中绘制了这个东西。我正在进入锁条带,看看是否适合我。 PS:小心尿布堆 ovl :)
  • 请在此处发布您的结果。也许是一个单独的答案。
猜你喜欢
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多