提问人:Matt Price 提问时间:8/9/2008 最后编辑:Alex MillerMatt Price 更新时间:9/26/2008 访问量:1569
在多核计算机上扩展多线程应用程序
Scaling multithreaded applications on multicored machines
问:
我正在做一个项目,我们需要更高的性能。随着时间的流逝,我们继续改进设计,使其更加并行(线程和分布式)。然后最新的步骤是将其的一部分移动到具有 16 个内核的新机器上。我发现我们需要重新思考如何做一些事情来扩展到共享内存模型中的这么多内核。例如,标准内存分配器不够好。
人们会推荐哪些资源?
到目前为止,我发现萨特的专栏《多布斯博士》是一个好的开始。 我刚刚买了《多处理器编程的艺术》和《关于英特尔线程构建模块的 O'Reilly》一书
答:
您可能想查看 Google 的性能工具。他们已经发布了用于多线程应用程序的 malloc 版本。它还包括一组不错的分析工具。
Jeffrey Richter 非常喜欢穿线。他的书中有几章是关于线程的,请查看他的博客:
http://www.wintellect.com/cs/blogs/jeffreyr/default.aspx。
FreeBSD 中的分配器最近得到了 FreeBSD 7 的更新。新的线程称为 jemaloc,显然在多线程方面更具可扩展性。
你没有提到你正在使用哪个平台,所以也许这个分配器对你有用。(我相信 Firefox 3 使用 jemalloc,即使在 Windows 上也是如此。所以端口必须存在于某个地方。
其他几本有帮助的书是:
- 同步算法和并发编程
- 并行编程模式
- C. A. R. Hoare 的 Communicating Sequential Processes(该链接中的经典免费 PDF)
此外,请考虑减少对并发进程之间共享状态的依赖。如果你能避免这种情况,你的扩展性会好得多,因为你将能够划分出独立的工作单元,而不必在它们之间做那么多的同步。
即使需要共享某些状态,也可以查看是否可以将共享状态与实际处理进行分区。这样一来,您就可以并行执行尽可能多的处理,而不必将已完成的工作单元集成回共享状态。显然,如果你在工作单元之间有依赖关系,这是行不通的,但值得研究,而不仅仅是假设状态总是要共享的。
正如 monty python 所说,“现在完全不同”——您可以尝试一种不使用线程但使用进程和消息传递(没有共享状态)的语言/环境。其中最成熟的是 erlang(以及这本优秀而有趣的书:http://www.pragprog.com/titles/jaerlang/programming-erlang)。可能与您的情况不完全相关,但您仍然可以学到很多想法,这些想法可以应用于其他工具。
对于其他环境:
.Net 具有 F#(用于学习函数式编程)。 JVM 有 Scala(它有 actor,非常像 Erlang,并且是函数式混合语言)。此外,还有 Doug Lea 的 Java “fork join”框架,它为您完成了很多艰苦的工作。
看看 Hoard,如果你正在做大量的内存分配。
滚动您自己的锁定免费列表。这里有一个很好的资源 - 它是用 C# 编写的,但想法是可移植的。一旦你习惯了它们的工作方式,你就会开始看到它们可以使用的其他地方,而不仅仅是在列表中。
我将不得不在某个时候签出 Hoard、Google Perftools 和 jemalloc。目前,我们使用的是英特尔线程构建模块的scalable_malloc,它的性能足够好。
无论好坏,我们都在Windows上使用C++,尽管我们的大部分代码都可以使用gcc进行编译。除非有令人信服的理由迁移到 redhat(我们使用的主要 linux 发行版),否则我怀疑是否值得为之头疼/政治麻烦。
我很想使用 Erlang,但现在还有很多事情要重做。如果我们考虑一下在电信环境中开发 Erlang 的要求,就会发现这与我们的世界(电子交易)非常相似。阿姆斯特朗的书在我阅读堆栈:)
在从 4 个内核扩展到 16 个内核的测试中,我学会了理解代码并行部分中任何锁定/争用的成本。幸运的是,我们有很大一部分可以随数据扩展,但由于额外的锁和内存分配器,即使这样一开始也不起作用。
我维护着一个并发链接博客,可能会引起人们的持续兴趣:
评论