gpt4 book ai didi

multithreading - 线程、Coro、Anyevent 混淆

转载 作者:行者123 更新时间:2023-12-05 01:23:48 26 4
gpt4 key购买 nike

我对 perl 相对较新,甚至对 perl 中的线程也较新。我有一个 perl 脚本,它从 3 个不同的来源获取输入。 (2 个 LDAP 查询和一个不总是存在的文件)因为某些部分可能比其他部分花费更长的时间,所以我决定使用线程和队列。在开发过程中,测试脚本的各个组件效果很好,但将它们放在一起后,性能似乎下降了。

基本结构是这里
2 个线程:(读取文件或读取 AD 条目)-> Queue1 -> 2 个线程:(清理数据)-> Queue2 -> 3-4 个线程(与现有的本地 LDAP 条目比较)。几个线程将统计信息报告回主脚本,一旦所有线程完成,就会发送一封电子邮件,其中包含该运行的所有统计信息和状态。

我正在使用 dequeue_nb,我认为这会有所帮助,但没有运气。

性能冲击似乎在排队。在寻找提高性能的技巧时,我遇到了几篇文章,说 perl 线程不好,可以使用 coro、POE、Anyevent、IO:async 等。

这似乎不是一个“事件”问题,所以我认为 AnyEvent 或 POE 不会是我所看到的方式,coros 似乎一次只使用一个 CPU,所以我不确定这也行。我考虑过使用它们的组合,但后来我的头开始受伤。有没有人对如何修复/排除我的脚本或如何实现其他模块之一有任何建议?

最佳答案

并行性的一个问题是同步。它是性能杀手,很糟糕,如果可能的话应该避免。

运维架构

让我们看看你的架构:

+--------------+--------------+
| Input 1 | Input 2 |
+--------------+--------------+
| QUEUE A |
+--------------+--------------+
| Scrub 1 | Scrub 2 |
+--------------+--------------+
| QUEUE B |
+---------+---------+---------+
| Compare | Compare | Compare |
+---------+---------+---------+

讨论

队列 A 必须跨四个线程同步;穿过 5-6 的队列 B。任何时候只有一个线程可以访问队列,所以大部分时间你的线程都在等待,不能工作!

并行管道架构

稍微不同的架构可能如下所示:
+-----------+    +-----------+
| Input 1 | | Input 2 |
+-----------+ +-----------+
| QUEUE 1A | | QUEUE 2A |
+-----------+ +-----------+
| Scrub 1 | | Scrub 2 |
+-----------+ +-----------+
| QUEUE 1B | | QUEUE 2B |
+-----+-----+ +-----+-----+
| Cmp | Cmp | | Cmp | Cmp |
+-----+-----+ +-----+-----+

讨论

在这里,A 队列只与两个线程相关联(-> 等待较少),B 队列只与三个线程相关联。对于类似的输入大小/复杂性,这种架构应该执行得更快。如果 Input 2 相当短,整个 Pipeline 2 将在 Pipeline 1 完成一半之前运行。但是,它比为每个管道使用单个进程要好得多。

草坪洒水器架构

概念

更好的架构会尝试将进程的输出分布到多个队列中。 (相反,当队列为空时,让线程从多个队列中获取输入是不好的。)

每个队列写入应该转到不同的队列:
  +-----------+   +-----------+
| Input 1 | | Input 2 |
+-----------+ +-----------+
| \ / |
+-----------+ +-----------+
| QUEUE 1A | | QUEUE 2A |
+-----------+ +-----------+
| Scrub 1 | | Scrub 2 |
+-----------+ +-----------+
/ | \ \ / / | \

+-------+-------+-------+-------+
| Q. 1B | Q. 2B | Q. 3B | Q. 4B |
+-------+-------+-------+-------+
| Cmp | Cmp | Cmp | Cmp |
+-------+-------+-------+-------+

这可以确保每个线程具有相同的工作负载,但不能确保所有线程同时完成。

讨论

所有队列在 3 个线程之间共享。问题是两个线程在写入队列时会相互阻塞。如果 Queue 写入访问之间的时间明显大于写入持续时间,这应该没有问题,否则可以混入第二种架构。

因此,这种架构是否有意义取决于您的确切要求。

对于均匀大小的输入,它的速度较慢,但​​在不规则输入上表现更好。

附录

实现时:

使用什么框架是次要的架构。如果您只传递文本字符串,我强烈建议您使用管道。如果您必须传递 Perl 数据类型或对象,您可能必须接受使用真实队列的额外开销:将非共享变量添加到队列时,还必须进行深度复制(请参阅@Leon Timmermans 答案)到所有同步开销。

关于可扩展性:

架构 1 和 3 的线程数不固定。我强烈建议使用这种灵 active 来对不同的组合进行基准测试。经验法则是您应该使用 n 到 2n 个线程,其中 n 是处理器(或硬件线程)的数量。这可以看作是一个阶段的线程的最大合理数。除此之外,您只会受到内存损失而没有加速。当一个阶段处理输入的速度比提供的速度快时,可能会更早地达到性能饱和点。

关于multithreading - 线程、Coro、Anyevent 混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11727655/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com