【问题标题】:Why do we need external sort?为什么我们需要外部排序?
【发布时间】:2015-02-06 04:35:02
【问题描述】:

外部排序的主要原因是数据可能比我们拥有的主内存大。但是,我们现在使用的是虚拟内存,虚拟内存会负责主内存和磁盘之间的交换。为什么我们要那么需要外部排序吗?

【问题讨论】:

  • 虚拟内存不是无限的,我猜是一回事
  • 这是否与磁带驱动器上的排序有关?我听说 knuth 对此有很多话要说。你的磁带驱动器可能比你的硬盘驱动器大很多(因此是最大的虚拟内存。)
  • @Oxinabox iirc 32 位 Windows 机器的虚拟内存限制为 16TB?需要仔细检查它。第二种选择是不支持 VM 的操作系统。第三,一些进程可能有他们可以使用的虚拟机受到管理员等的限制。
  • 实内存中的随机内存访问需要几纳秒。硬盘上的随机磁盘查找需要几毫秒。当我们实际使用虚拟内存时,具有错误访问模式的程序会导致大量磁盘寻道花费了很长时间,以至于看起来它们已经失败了。这些天真正发生的是物理内存非常大,以至于对于几乎所有大小的问题,一旦从磁盘读取数据,它就会保留在物理内存的缓存中,并且永远不必再次从中读取。
  • 具有高度不均匀访问时间的机械设备的大容量存储正在成为过去 - 想想 TB 分米远,泽字节大约 100 公里。

标签: algorithm sorting virtual-memory external-sorting


【解决方案1】:

外部排序算法使大量数据的排序变得高效(即使数据不适合物理 RAM)。

虽然使用内存排序算法和虚拟内存满足了外部排序的功能要求(即对数据进行排序),但未能实现高效的非功能要求。一个好的外部排序可以最大限度地减少读取和写入外部存储的数据量(以及历史上的寻道时间),并且在不是为此而设计的排序算法之上的通用虚拟内存实现不会与设计为最小化 IO。

【讨论】:

    【解决方案2】:

    除了@Anonymous 的回答是外部排序更好地优化了更少的磁盘 IO,有时使用内存排序和使用虚拟内存是不可行的,因为虚拟内存空间小于文件的大小。

    例如,如果你有一个 32 位系统(仍然有很多),并且你想对一个 20 GB 的文件进行排序,32 位系统允许你有 2^32 ~= 4GB 的虚拟地址,但是您尝试排序的文件无法放入。

    当 64 位系统还不是很普遍时,这曾经是一个真正的问题,而今天对于旧的 32 位系统和一些嵌入式设备来说仍然是一个问题。


    但是,即使对于 64 位系统,正如前面的答案所解释的,外部排序算法针对排序的性质进行了更优化,并且与让操作系统“处理事情”相比,所需的磁盘 IO 显着减少。

    【讨论】:

      【解决方案3】:

      我使用的是 Windows,在常用的 shell 中,您可以运行“systeminfo”,它会为我提供笔记本电脑的内存使用信息。

      Total Physical Memory:     8,082 MB
      Available Physical Memory: 2,536 MB
      Virtual Memory: Max Size:  11,410 MB
      Virtual Memory: Available: 2,686 MB
      Virtual Memory: In Use:    8,724 MB
      

      我只是编写了一个应用程序来测试我可以从我的笔记本电脑初始化的数组的最大大小

      public static void BurnMemory()
      {
          for(var i = 1; i <= 1024; i++)
          {
              long size = 1 << i;
              long t = 4 * size / (1 << 30);
              try
              {
                  // 1 int32 takes 32 bit(4 byte) memmory, 
                  var arr = new int[size];
      
                  Console.WriteLine("Test pass initialize a array with size = 2^" + i.ToString());
              }
              catch(OutOfMemoryException err)
              {
                  Console.WriteLine("Reach memory limitation when initialize a array with size = 2^{0} int32 = 4 x {1}B= {2}TB",i, size, t );
                  break;
              }
          }
      }
      

      它似乎在尝试初始化大小为 2^29 的数组时终止。

      Reach memory limitation when initialize a array with size = 2^29 int32 = 4 x 536870912B= 2TB
      

      我从测试中得到什么:

      • 达到内存限制并不难。
      • 我们需要了解我们服务器的能力,然后决定是使用内存排序还是外部排序。

      【讨论】:

        猜你喜欢
        • 2022-12-05
        • 2019-06-09
        • 2014-06-18
        • 2017-02-26
        • 2011-04-03
        • 2017-07-27
        • 2020-09-21
        • 2020-03-09
        • 2018-12-24
        相关资源
        最近更新 更多