首页 > 解决方案 > 拍摄线程的快照

问题描述

我有一个由许多线程(超过 100 个)组成的程序。由于线程众多,程序所需的内存非常昂贵,所以我无法在我的 PC 上运行它。

我有一个运行程序的想法。设线程数为 100。

1- i=1, flag = false
2- if(flag == true) reconstruct thread[i], thread[i+1], ..., thread[i+9] from snapshots file[i], file[i+1], ..., file[i+9]
3- run thread[i], thread[i+1], ..., thread[i+9] for one second
4- take a snapshots of thread[i], thread[i+1], ..., thread[i+9], and write the snapshots on file[i], file[i+1], ..., file[i+9]
5- kill thread[i], thread[i+1], ..., thread[i+9] 
6- i = i + 10
7- if(i < 100) go to line 3 
   else i = 1, flag = true, go to line 2

如何用 C++ 或 C# 实现这个想法?

标签: multithreadingconcurrencymultiprocessing

解决方案


我担心您正在考虑在不知道操作系统为您做什么的情况下实现操作系统的大部分。

操作系统管理虚拟内存和运行线程。如果您有很多线程,并且每个线程中有很多数据,那么如果总内存使用量超过 RAM,那么运行所有这些将是一个挑战。但是,操作系统将使用某种描述的页面文件作为您计算机中虚拟内存系统的一部分。这导致虚拟内存大小受 HDD 大小的限制,而不是安装的 RAM。

现在,您谈论备份/恢复线程。去哪儿?大概你的意思是磁盘。但是,您的程序执行自己的备份/还原到磁盘与操作系统通过虚拟内存系统及其页面文件为您执行此操作之间没有根本区别。在这两种情况下,您最终都会得到无法存储在磁盘上的 RAM 中的数据:

  • 如果您只是在线程内分配和填充内存,操作系统将通过页面文件在后台为您完成所有工作,最重要的是,您不必编写任何代码来执行此操作。

  • 但是,如果您编写程序来将数据保存/恢复到 HDD,那么您已经编写了很多源代码,并且您最终不会得到比让操作系统继续运行更好的任何东西。

因此,如果两种方式最终得到相似的结果,那么性能相似也就不足为奇了。就是这样; 许多线程颠簸虚拟内存页面文件很慢。不同之处在于操作系统已经开发了很多年,以使其尽可能好(即协调线程调度与有效使用页面文件),您很可能无法成功击败它。

这就是线程池有用的原因。您无需设置大量线程(每个线程执行一项任务),而是将大量任务提交到线程池并让池管理如何最好地运行这些任务。如果单个任务不依赖于另一个任务做某事(例如发布信号量等),这将特别强大。

如果使用得当,线程池将尽可能地浏览提交的任务列表,因为它发现自己正在运行的硬件。这使您不必编写代码来了解自己的机器架构(您是否对优化线程数与内核数感兴趣)。

它还可能导致虚拟内存系统对页面文件执行更少的分页,这意味着 HDD 抖动将减少到最低限度。这是因为在任何时候运行的线程(嗯,任务)要少得多,所以只有那些任务的数据会被分页到 RAM 中。

所以这就是我要做的。使用线程池而不是大量单独的线程,依靠操作系统有效地管理所有虚拟内存,并避免编写大量复制操作系统功能的代码。

如果这仍然不够快,那么您将不得不购买一台更大的计算机,或者开始编写代码以在计算机集群中以分布式方式运行。ZeroMQ 和 OpenMPI 只是帮助实现这一目标的两种不同方式(OpenMPI 是超级计算机专家最喜欢的一种)。


推荐阅读