3

我有一个非常大的单例对象,其中包含一个 2500 X 80000 双数组。当我尝试在多线程环境中访问它时,随着线程数量的增加,访问对象的时间也会增加。如果有办法我可以保持对象的访问时间相同,而与线程数无关。

我只是在读取数组。数组中没有进行任何更改。代码中没有同步

4

3 回答 3

1

如果您所做的只是阅读,那么您将拥有最有效的解决方案软件。更可能的问题是您正在耗尽资源,例如,您拥有的线程多于 CPU,或者您拥有的数据多于无法有效放入缓存中。

例如,如果您有一个线程,它可以完全访问您的 L3 缓存,例如 12 MB。如果你有两个线程,如果没有重叠,每个 cpu 可以使用一半的缓存。如果你有 24 个线程,那么每个 CPU 只有 0.5 MB,它必须共享一个高度竞争的资源。

在我所做的测试中,您可以根据您的操作仅使用 2-3 个线程来最大化 L3 缓存的带宽。

顺便说一句:如果您愿意,您应该获得更好的缓存效率。

  • 购买具有更大 L3 缓存和更宽内存带宽的 CPU,您可以获得高达 24 MB 的 2011 pin Xeon 处理器。
  • 使用 float 或 int 而不是 double。对于某些用例,我使用了带有两个固定小数位的 short。

我只是在读取数组。数组中没有进行任何更改。代码中没有同步

在一个地方,我看到每个关键线程都在自己的机器上运行。这将保证您的持续性能。但是,我怀疑,您需要考虑可以充分利用硬件并意识到您的硬件有限制的选项(例如您的预算;)

于 2013-06-16T18:42:29.543 回答
1

问题的一个可能原因是缓存无效。缓存取决于线程在有足够的其他缓存活动将行推出缓存之前返回到该行。随着线程数量的增加,线程重用一行的概率会下降。

如果可能的话,以自然顺序访问数组,第二个索引变化最快。这会尽快重用行并减少每个线程运行良好所需的缓存空间量。

一个可能的解决方案是使用信号量来限制同时读取数组的线程数,使其达到最高吞吐量。这可能大于一,但不会是无限的。

另一种解决方案是增加处理器的数量,从而增加与线程数成比例的缓存空间。

第三种选择是使用这么多线程重新访问。拥有一个有限的线程池和一个供他们处理的任务队列可能会更有效。

于 2013-06-16T17:38:03.063 回答
0

我终于找到了解决我的问题的方法。我没有将数据存储在二维数组中,而是将数据存储在单维数组中,结果比将相同的数据存储在二维数组中要快得多。显然,java 处理二维数组的效率不如一维数组。

于 2013-06-19T11:59:11.850 回答