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

2019 年 12 月 3 日 机器之心

选自pythonspeed

作者:Itamar Turner-Trauring

机器之心编译

参与:高璇、杜伟

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

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


原因是没有足够的内存——如果你只有 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/

「WAIC 开发者·临港人工智能开发者大会」将于 2019 年 12 月 6 日-7 日上海临港举办。本次大会设有主题演讲、开发者工作坊、开发者挑战赛、技术和产业闭门研讨会等环节。邀请全球AI开发者在现场:听前沿理论+学实战干货+动手挑战赛。点击阅读原文,立即报名。

登录查看更多
0

相关内容

软件(中国大陆及香港用语,台湾作软体,英文:Software)是一系列按照特定顺序组织的计算机数据和指令的集合。一般来讲软件被划分为编程语言、系统软件、应用软件和介于这两者之间的中间件。软件就是程序加文档的集合体。
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
【实用书】流数据处理,Streaming Data,219页pdf
专知会员服务
76+阅读 · 2020年4月24日
TensorFlow Lite指南实战《TensorFlow Lite A primer》,附48页PPT
专知会员服务
68+阅读 · 2020年1月17日
【模型泛化教程】标签平滑与Keras, TensorFlow,和深度学习
专知会员服务
20+阅读 · 2019年12月31日
教程 | 从零开始搭建『深度学习』GPU开发环境
机器学习算法与Python学习
8+阅读 · 2019年10月28日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
GPU 显存不足怎么办?
AINLP
13+阅读 · 2019年8月16日
教程 | PyTorch经验指南:技巧与陷阱
机器之心
15+阅读 · 2018年7月30日
深度学习训练数据不平衡问题,怎么解决?
AI研习社
7+阅读 · 2018年7月3日
【强烈推荐】浅谈将Pytorch模型从CPU转换成GPU
机器学习研究会
7+阅读 · 2017年12月24日
手把手教你安装深度学习软件环境(附代码)
数据派THU
4+阅读 · 2017年10月4日
从零开始:深度学习软件环境安装指南
机器之心
5+阅读 · 2017年10月2日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Learning to See Through Obstructions
Arxiv
7+阅读 · 2020年4月2日
Monocular Plan View Networks for Autonomous Driving
Arxiv
6+阅读 · 2019年5月16日
Arxiv
3+阅读 · 2018年3月13日
Arxiv
12+阅读 · 2018年1月12日
VIP会员
相关资讯
教程 | 从零开始搭建『深度学习』GPU开发环境
机器学习算法与Python学习
8+阅读 · 2019年10月28日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
GPU 显存不足怎么办?
AINLP
13+阅读 · 2019年8月16日
教程 | PyTorch经验指南:技巧与陷阱
机器之心
15+阅读 · 2018年7月30日
深度学习训练数据不平衡问题,怎么解决?
AI研习社
7+阅读 · 2018年7月3日
【强烈推荐】浅谈将Pytorch模型从CPU转换成GPU
机器学习研究会
7+阅读 · 2017年12月24日
手把手教你安装深度学习软件环境(附代码)
数据派THU
4+阅读 · 2017年10月4日
从零开始:深度学习软件环境安装指南
机器之心
5+阅读 · 2017年10月2日
Spark的误解-不仅Spark是内存计算,Hadoop也是内存计算
Top
微信扫码咨询专知VIP会员