内存不足、钱包不鼓怎么办?三种技巧助你摆脱内存使用困境

在编写软件的过程中,开发人员需要处理大量的数据,因而常常会遇到内存不足的情况。虽然我们都知道,解决内存不足的简单粗暴方法就是往里砸钱,但有时自己的经济实力不允许这么任性。本文作者提出了三种技巧:数据压缩、分块和索引,以此从软件本身解决了内存不足的窘境。

在你编写用于处理数据的软件时,当只用一个小的示例文件做测试,软件就可以很好地运行。但是,当加载实际数据时,程序立刻崩溃。

原因是没有足够的内存——如果你只有 16GB 的 RAM,则无法加载 100GB 的文件。有时操作系统耗尽内存,导致内存无法分配,程序就只能崩溃。

所以,你可以做什么?要启动一个大数据集,需要做的是:

  • 获取计算机集;

  • 花一周的时间进行设置;

  • 在很多情况下,学习全新的 API 并重写所有代码。

这样做简直让人心力交瘁;幸运的是,在许多情况下,你也不必这么做。

你只需一种简单易用的解决方案:在一台计算机上用最少的设置即可处理数据,并且尽可能使用你已经在用的库。而且在很多时候,你可以使用一种被称为「核外计算」的技术来实现。

在本文中,作者将介绍:

  • 为什么需要 RAM;

  • 处理内存中不适配数据的最简单方法:花钱;

  • 处理过多数据的三种基本软件使用技巧:压缩、组块和索引。

文章接下来将展示如何将这些技术应用于 NumPy 和 Pandas 等特定库。

为什么需要 RAM?

在继续讨论解决方案之前,让我们先阐明问题出现的原因。你可以使用计算机的内存(RAM)读取和写入数据,但是硬盘驱动器也可以读取和写入数据——那么为什么计算机需要 RAM 呢?而且磁盘比 RAM 便宜,它通常可以包含所有数据,那么为什么代码不能改为仅从磁盘读取和写入数据呢?

从理论上讲,这是可行的。但即使是更新、更快的固态硬盘(SSD)也比 RAM 慢得多:

  • 从 SSD 读取:约 16,000 纳秒

  • 从 RAM 读取:约 100 纳秒

如果想要快速计算,数据必须匹配 RAM,否则代码运行速度可能会慢 150 倍。

解决方案:更多 RAM

解决内存不足的最简单粗暴的方法就是往里砸钱。你可以买台计算机或者租用云虚拟机(VM),后者的内存比大多数笔记本电脑都要多。以 2019 年 11 月市场价为例,你可以:

  • 购买具有 6 核和 64GB RAM 的 Thinkpad M720 Tower,价格为 1074 美元;

  • 租用具有 64 核和 432GB RAM 的云虚拟机,每小时 3.62 美元。

这些只是我简单搜索得到的价格,如果进行一些深入研究,则可能需要更全的价格和产品。

如果花钱就能解决你的内存问题,那通常是最便宜的解决方案:毕竟时间就是金钱。但是,有时花钱也解决不了问题。

例如,如果你要处理许多数据任务,在一段时间内,云计算可能是很顺手的解决方案,但却也是昂贵的解决方案。在一项研究工作中,我所使用软件的计算成本将耗尽该产品的所有预计收入,包括我的薪水在内,这样代价就太大了。

如果购买/租用更多的 RAM 是不够或不现实的,下一步就是弄清楚如何通过更改软件来减少内存使用。

技巧 I:数据压缩

数据压缩意味着使用更少的内存来表示数据。压缩有两种形式:

  • 无损:存储的数据与原始数据信息完全相同;

  • 有损:存储的数据丢失了原始数据中的某些细节,但在理想情况下不会对计算结果产生太大影响。

请注意,我说的不是 ZIP 或 gzip 文件,因为这些文件通常涉及磁盘压缩。要处理 ZIP 文件中的数据,首先需要解压缩到 RAM 中。因此,这无济于事。

你需要的是压缩内存中的表示形式。

例如,假设你的数据有两个值,并且将永远只有这两个值:"AVAILABLE"和"UNAVAILABLE"。你可以将它们存储为布尔值,True 或 False,这样可以将其存储为 1 个字节,而不是每个条目都要占用 10 个甚至更多字节。你甚至可以将表示降低到表示布尔值所需的单个位,从而将内存使用量减少到原来的八分之一。

技巧 II:分块,一次加载一个数据块

当你需要处理所有数据但不需要一次将所有数据加载到内存中时,分块很有用。你可以将数据分块加载到内存中,一次只处理一个数据块(或者按照后文提到的,并行处理多个块)。

例如,假设你要查找一本书中最长的单词。你可以一次将所有数据加载到内存中:

largest_word = ""
for word in book.get_text().split():
    if len(word) > len(largest_word):
        largest_word = word

即使假设在我们的情况下,书不适配内存,可以将其改为一页一页的加载。

largest_word = ""
for page in book.iterpages():
    for word in page.get_text().split():
        if len(word) > len(largest_word):
            largest_word = word

你需要使用的内存要少得多,因为在任何给定的时间内只有一页书在内存中只有一页书在内存中。最后,你还是会得到相同的答案。

技巧 III:在你需要数据子集时进行索引

当你只需要使用数据的一个子集,并且希望在不同的时间加载数据的不同子集时,索引很有用。

你可以通过分块解决这种情况:每次加载所有数据,然后过滤掉不需要的数据。但这很慢,因为需要加载许多不相关的数据。

如果只需要部分数据,则最好使用索引,而不是分块,索引最好使用数据摘要,它可以告诉你在哪里找到所需的数据。

想象一下,您只想阅读本书中有关土豚(ardarvarks)的部分。如果使用分块,则需要逐页阅读整本书,以查找 ardarvarks,但这将花费相当长的时间。

或者,你可以利用书的索引,找到「Aardvarks」的条目。它可能会告诉你阅读第 7、19 和 120-123 页。现在你就可以阅读这些页面,并且仅阅读这些页面,这要快得多。

这样之所以可行,是因为索引比整本书要小得多,因此将索引加载到内存中以查找相关数据要容易得多。

最简单的索引技术

实现索引的最简单、最常见方法是在目录中命名文件:

mydata/
    2019-Jan.csv
    2019-Feb.csv
    2019-Mar.csv
    2019-Apr.csv
    ...

如果要获取 2019 年 3 月的数据,则只需加载 2019-Mar.csv 即可,而无需加载 2 月、7 月或任何其他月份的数据。

下一步:应用这些技术

解决 RAM 不足的最简单方法是花钱获得更多 RAM。但是,如果这行不通或者不现实时,就可以使用压缩、分块或索引等技巧。

这些技巧可以应用在许多不同的软件包和工具中。即使大数据系统也基于这些技巧构建:例如,使用多台计算机来处理数据块。

原文链接:https://pythonspeed.com/articles/data-doesnt-fit-in-memory/

入门更新软件内存不足
1
相关数据
数据压缩技术

数据压缩是指在不丢失有用信息的前提下,缩减数据量以减少存储空间,提高其传输、存储和处理效率,或按照一定的算法对数据进行重新组织,减少数据的冗余和存储的空间的一种技术方法。数据压缩包括有损压缩和无损压缩。在计算机科学和信息论中,数据压缩或者源编码是按照特定的编码机制用比未经编码少的数据位元(或者其它信息相关的单位)表示信息的过程。

云计算技术

云计算(英语:cloud computing),是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需求提供给计算机各种终端和其他设备。

推荐文章
暂无评论
暂无评论~