代码之家  ›  专栏  ›  技术社区  ›  BuschnicK

跨线程的协同内存使用?

  •  2
  • BuschnicK  · 技术社区  · 16 年前

    我有一个应用程序,它有多个线程处理来自TODO队列的工作。我对进入队列的内容和顺序没有影响(它是由用户外部提供的)。队列中的单个工作项可能需要几秒到几个小时的运行时间,并且在处理过程中不应中断。另外,一个工作项可能会占用几兆到大约2GB的内存。内存消耗是我的问题。我在8GB机器上以64位进程的形式运行,有8个并行线程。如果它们中的每一个同时命中最坏情况的工作项,我的内存就会耗尽。我想知道解决这个问题的最佳方法。

    1. 保守计划,只运行4个线程。最坏的情况应该不再是问题了,但是我们浪费了很多并行性,使得平均情况慢了很多。
    2. 在开始新的项目之前,使每个线程检查可用的内存(或者更确切地说,所有线程分配的总内存)。仅在剩余2GB以上内存时启动。定期复查,希望其他线程可以完成它们的内存占用,我们最终可以开始。
    3. 尝试预测队列中需要多少内存项(硬),并相应地计划。我们可以重新排序队列(覆盖用户选择),或者简单地调整正在运行的工作线程的数量。
    4. 更多的想法?

    我目前倾向于数字2,因为它似乎很容易实现和解决大多数情况。然而,我仍然想知道,有什么标准的方法来处理这种情况?毕竟,操作系统必须在流程级别上执行非常类似的操作…

    当做,

    Sören
    
    3 回复  |  直到 16 年前
        1
  •  3
  •   gavinb    16 年前

    所以您当前最坏的内存使用率是16GB。只有8GB的RAM,在操作系统和系统进程占有它们的份额之后,您就有6或7GB的内存了。所以平均来说,在一个适度加载的系统上,你已经在改变内存了。这台机器有多少个内核?您是否有8个工作线程,因为它是一个8核机器?

    基本上,您可以减少内存消耗,或者增加可用内存。您的选项1,只运行4个线程,在利用CPU资源的情况下,它可以将吞吐量减半——绝对是次优的。

    选项2是可能的,但有风险。内存管理非常复杂,查询可用内存并不能保证您能够继续进行分配(而不会导致分页)。磁盘I/O突发可能导致系统增加缓存大小,后台进程可能启动并在其工作集中交换,以及任何其他因素。由于这些原因,可用内存越小,您对它的依赖就越少。此外,随着时间的推移,内存碎片也会导致问题。

    选项3很有趣,但很容易导致CPU负载不足。如果您运行的作业具有较高的内存需求,那么最终可能只运行几个线程,并且与选项1(您正在加载核心)处于相同的情况。

    因此,采用“减少消耗”策略,您真的需要将整个数据集同时保存在内存中吗?根据算法和数据访问模式(如随机和顺序),您可以逐步加载数据。更深奥的方法可能涉及压缩,这取决于您的数据和算法(但实际上,这可能是浪费精力)。

    然后是“增加可用内存”。在价格/性能方面,您应该认真考虑购买更多RAM。有时,投资更多的硬件比开发时间更便宜,以获得相同的最终结果。例如,您可以花几百美元放入32GB的RAM,这将立即提高性能,而不会给解决方案增加任何复杂性。在性能压力关闭的情况下,您可以对应用程序进行分析,以了解在哪里可以提高软件的效率。

        2
  •  1
  •   BuschnicK    16 年前

    我在Herb Sutter的博客上继续讨论,并提出了一些非常有帮助的读者评论。前往 Sutter's Mill 如果你感兴趣的话。

    感谢您迄今为止提出的所有建议!

    Sören
    
        3
  •  0
  •   Tim Croydon    16 年前

    很难在不确切知道自己在做什么的情况下提出解决方案,但是如何考虑:

    1. 看看您的处理算法是否可以在不将整个工作项加载到内存中的情况下访问较小部分的数据。
    2. 考虑开发一个基于服务的解决方案,以便工作由另一个流程(可能是Web服务)执行。通过这种方式,您可以将解决方案扩展为在多个服务器上运行,或者使用负载均衡器来分发工作。
    3. 在处理传入的工作项之前,是否将其保存到磁盘?如果不是,它们可能无论如何都应该是,特别是在处理器到达它们之前可能需要一段时间。
    4. 内存使用率与传入工作项的大小成比例,还是易于计算?了解这一点有助于决定如何安排处理。

    希望有帮助?!