1

你能给我解释一下这个废话吗?我有一个基本上用数学运算填充数组的方法。不涉及 I/O 或任何东西。现在,这个方法运行大约需要 50 秒,并且代码是完全可扩展的(理论上 100%),所以我把它分成 4 个线程,等待它们完成,然后重新组装 4 个数组。现在,我在四核处理器上运行程序,预计需要大约 15 秒,而实际上需要 58 秒。没错:它需要更长的时间!我看到 cpu 工作 100%,我知道每个线程执行 1/4 的计算,创建线程和重新组装数组总共需要大约 1-2 毫秒。是什么导致了这种性能损失?这段时间cpu到底在做什么?代码: http: //pastebin.com/cFUgiysw

4

4 回答 4

0

除非您不断地创建和终止线程,否则线程开销应该不是问题。四个线程同时运行对调度程序来说没什么大不了的。

正如 Peter Lawrey 所说,内存带宽可能是问题所在。您的 50 秒代码在 Java 引擎上运行,它们都在争夺可用的内存带宽。Java 引擎需要内存带宽来执行您的代码,而您的代码需要它来进行计算。

您编写“完全可扩展”,如果您的代码被编译,就会出现这种情况。由于它在 Java 引擎上运行,因此并非如此。因此,总时间增加 16% 可以看作是一个线程的平滑度与四个内存访问冲突的混乱度之间的差异。

于 2012-08-18T18:19:47.923 回答
0

线程不是那样工作的。

线程仍然是同一进程的一部分(取决于操作系统),因此就操作系统而言 - 1 个进程中的 4 个线程的 CPU 时间将被安排为与 1 个进程中的 1 个线程相同。

此外,由于值如此之少,您不会在开销中看到可伸缩性。在 java 中重新组装数组将是昂贵的。

查看诸如“上下文切换开销”之类的内容-当您尝试将理论映射到实践时,此类内容总是会让您感到困惑:P

我会坚持单线程方式:)

~ 丹

http://en.wikipedia.org/wiki/Context_switch

于 2012-08-18T08:20:40.087 回答
0

打开新线程会产生成本。我认为它不应该长达 8 秒,但这取决于您使用的线程。一些线程需要创建您正在处理的数据的副本以保证线程安全,这可能需要一些时间。这个成本通常被称为开销。如果您正在执行的执行是不可序列化的,例如读取相同的文件或需要访问共享资源,线程可能需要相互等待,这可能需要一些时间,并且在次优条件下,它可能需要比串行执行更多的时间. 我的建议是尝试检查这些不可序列化的事件,如果可能的话,将它们从线程部分中删除。还可以尝试使用较少数量的线程 4 个线程用于 4 个 CPU 并不总是最佳的。

希望能帮助到你。

于 2012-08-18T08:23:47.603 回答
0

很大程度上取决于您在做什么以及如何分配工作。这个问题有很多可能的原因。

  • 最可能的原因是,您正在通过一个线程将 CPU 的所有带宽用于主内存总线。如果您的数据集大于 CPU 缓存,则可能会发生这种情况。尤其是如果您有一些随机访问行为。您可以考虑尝试重用原始数组,而不是采用多个副本来减少缓存流失。
  • 您的锁定开销大于性能增益。我怀疑您使用了非常课程锁定,所以这不应该是一个问题。
  • 开始停止线程需要很长时间。由于您的代码是多秒的,我也对此表示怀疑。
于 2012-08-18T08:27:27.883 回答