0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

内存比较小的时候碰到大量数据应该如何解决

Wildesbeast 来源:搜狐新闻 作者:Hadoop技术博文 2019-12-15 12:20 次阅读

当你写了一个处理数据的软件,它可能在小样本文件上运行地很好,但一旦加载大量真实数据后,这个软件就会崩溃。

问题在于你没有足够的内存——如果你有 16GB 的 RAM ,你就无法一次载入 100GB 大小的文件。载入这么大的文件时,操作系统在某个时刻就会耗尽内存,不能分配存储单元,你的程序也就会崩溃。

所以,你该怎样防止这类情况发生?你可以启动一个大数据集群——你所需要做的是:

搞到一个计算机集群。

花一周时间搭建这个集群。

大部分情况下,你需要学习一套全新的 API,重写你所有的代码。

这个代价可能很昂贵,会令人沮丧;幸运的是,大部分情况下,我们不必这样做。

你需要一个简单而容易的解决方案:在单机上处理你的数据,最小化环境搭建开销,尽可能利用你正在使用的代码库。实际上,大部分情况你都可以做到这样,只要使用一些方法即可,有时候这些方法被称为“核外计算”(out-of-core computation)。

本文将介绍如下内容:

你究竟为什么需要 RAM。

处理无法放入内存的数据最简单的方法:花些钱。

处理大量数据的三种基本软件方法:压缩、分块、索引

之后的文章将会展示如何把这些方法应用到诸如 NumPy 和 Pandas 这样的库中。

1你究竟为什么需要 RAM?

在我们开始解释解决方案前,我们要弄清楚该问题是如何产生的。我们的计算机内存(RAM)能让你读写数据,但是你的硬盘也可以读写数据——那为什么计算机还需要 RAM 呢?硬盘比 RAM 更便宜,所以它通常大到能够容纳下你的所有数据,那为什么你的代码不能直接从硬盘读写数据呢?

理论上讲,这也行得通的。但是,即使是最现代化且速度很快的 SSD 硬盘也比 RAM 慢太多:

从 SSD 上读取数据: 大约 1.6 万纳秒

从 RAM 上读取数据: 大于 100 纳秒

如果你想要实现快速计算,数据就只能放在 RAM 中,否则你的代码运行时就会慢上 150 倍。

2资金方面的解决方案:购买更多的 RAM

没有足够 RAM 时的最简单解决方案就是花钱来解决。你要么购买一台计算机,或者租一台云端的虚拟机(VM:Virtual Machine,这会比大多数笔记本电脑贵得多)。2019 年 11 月,我稍微调研了一下,在价格方面做了一些比较,发现你可以这样:

购买 一台 Thinkpad M720 Tower,它有 6 个核和 64GB RAM,价格是 1074 美金。

租用 一台云端的 VM,它有 64 个核和 432GB RAM,价格是每小时 3.62 美金。

这只是我稍微调研后发现的数字,再继续调研下去,你会发现更好的方案。

如果花钱购买硬件可以把你的数据读入 RAM,这通常就会是一个最经济的解决方案:毕竟你的时间相当宝贵。但是,有时候,这还不够解决这个问题。

例如,如果你要运行许多数据处理任务,在一段时期内,云计算可能是一个自然能想到的解决方案,但也是一个昂贵的解决方案。曾经在一个工作中,我的软件项目需要的计算开销几乎快用完了我们产品所有的预期收入,包括支付我薪水所需的至关重要的那部分收入。

如果购买 / 租用更多的 RAM 不足以满足需求或者根本行不通时,下一步就应该考虑如何通过修改软件来减少内存使用了。

3技巧 #1:压缩

压缩意味着用一种不同的表达形式表示你的数据,这种形式能占用更少内存。有两种方式来压缩:

无损压缩: 存储的数据包含的信息和原始数据包含的信息完全相同。

有损压缩: 存储的数据丢失了一些原始数据里的细节信息,但是这种信息丢失理想情况下不会对计算结果造成什么影响。

我想说明的是,我不是在谈论使用 ZIP 或者 gzip 工具来压缩文件,因为这些工具通常是对硬盘上的文件进行压缩的。为了处理 ZIP 压缩过的文件,你通常需要把这个文件载入内存中再进行解压缩为原始文件大小,所以这其实对内存节省没有什么帮助。

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

例如,比如说你的数据有两个值,一共也只会有两个值:“AVAILABLE”(代表可能取到的值)和“UNAVAILABLE”(代表不可能取到的值)。我们可以不必将其存为 10 个或更多字节的字符串,你可以将其存为一个布尔值,用 True 或者 False 表示,这样你就可以只用 1 个字节来表示了。你甚至可以继续压缩至 1 位来表示布尔值,这样就继续压缩到了 1 个字节时的 1/8 大小。

4技巧 #2:分块,每次只加载所有数据里的某一块

当你需要处理所有数据,而又无需把所有数据同时载入内存时,分块是很有用的。你可以把数据按块载入内存,每次计算一块的数据(或者正如我们要在今后一篇文章里想讨论的,可以多块并行处理)。

例如,比如说,你想搜索一本书里的最长单词。你可以一次性将所有数据载入内存:

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

这样你使用的内存就大大减少了,因为你一次只需要把这本书的一页载入内存,而最后得到的结果仍然是正确的。

5技巧 #3:当你需要数据的一个子集时,索引会很有用

当你需要数据的一个子集时,索引会很有用,使用索引你可以在不同时刻加载数据的不同子集。

你也可以用分块解决这个问题:每次加载所有的数据,过滤掉你不想要的数据。但这会很慢,因为你加载了很多不相关的数据。

如果你只需要部分数据,不要使用分块,最好使用索引,它可以告诉你到哪里能找出你关心的那部分数据。

想象一下,你只想阅读书本中关于土豚的章节。如果你运用分块技术,你得载入整本书,一页一页的载入,每页地搜寻土豚——但这要花很长时间才能完成。

或者说,你可以直接阅读这本书的末尾部分,也就是书本的索引部分,然后找到“土豚”的索引项。它可能会告诉你在第 7、19 页以及 120-123 页可以读到相关内容。所以,现在你可以只读那几页,这样就快多了。

这样很有效,因为索引比整本书占用的空间要小很多,所以把索引载入内存找出相关内容所在就会更容易。

6最简单的索引技巧

最简单也最常用的实现索引的方法就是在目录里给文件恰当命名:

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

如果你想要 2019 年 3 月数据,你就只需要加载 2019-Mar.csv 这个文件——而不用加载 2 月、7 月或者其他任何月份的数据。

7下一步:应用这些技巧

RAM 不够用,最简单的解决方法就是花钱买更多的 RAM。但是,如果这个方案无法实现或者仍然不够用时,你就需要使用压缩、分块或者索引来解决。

这些方法也出现在其他许多不同的软件包和工具中。即使是大数据系统也是建立在这些方法之上的:例如使用多个计算机来处理分块数据。

在接下来的文章里,我会给你展示如何使用具体的库和工具(NumPy、Pandas,或者用 ZIP 工具压缩文件)来应用这些方法。如果在我写完这些文章时,你就想阅读到它们,请在下方表格里注册我的通讯简报(newsletter)。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RAM
    RAM
    +关注

    关注

    8

    文章

    1367

    浏览量

    114517
  • 程序
    +关注

    关注

    116

    文章

    3773

    浏览量

    80835
  • 大数据
    +关注

    关注

    64

    文章

    8863

    浏览量

    137280
收藏 人收藏

    评论

    相关推荐

    ADAS1000数据读取后DRDY引脚无法回到高电平的情况应该何解决?

    排除所烧录的程序问题,请问出现这种故障应该何解决,硬件电路连接相比较之前没有做出改变,但PCB的走线可能有所变化,请问走线的变化是否会引起这种变化?目前ADAS1000数据读取后DR
    发表于 12-27 08:06

    TLV3502比较器输出幅值较小且有很多毛刺如何解决?

    电路原理图如上图所示TLV3502接成窗口比较器结构 上限电平为5V 下限电平为可调节 设为0.8V 输出通过或非门逻辑 得到OUT 图中R8未连 R9为10K OUT的波形从原理上应该为5V方波 实际为 幅值较小 且有很
    发表于 08-21 08:09

    碰到仿真器连接不上C2000芯片的时候何解决?

    看到很多坛友碰到仿真器连接不上芯片的问题常常一筹莫展。所以谈谈当碰到仿真器连接不上C2000芯片的时候该怎么办。首先,由于对工程师而言C2000芯片是黑盒,仿真器也是黑盒,所以我们无法从本质上确认
    发表于 07-23 09:02

    何解决DMA传输数据内存的问题?

    如何减少存储空间?如何控制脉冲数量?如何解决DMA传输数据内存的问题?
    发表于 12-21 07:53

    QCC3005芯片Line IN 听歌的时候声音比较小是什么原因

    QCC3005芯片 Line IN 听歌的时候声音比较小,这时候用ADK config tool工具连上,这时候声音就变大了,这是什么原因呢,怎么让Line in接通音乐的
    发表于 01-14 07:59

    Keil编译错误improper fixup应该何解

    本文档的有内容详细介绍的是Keil编译错误improper fixup应该何解决。
    发表于 07-31 17:35 1次下载
    Keil编译错误improper fixup<b class='flag-5'>应该</b>如<b class='flag-5'>何解</b>决

    ORCAD原理图中有哪些常见DRC错误应该何解

    本文档的主要内容详细介绍的是ORCAD原理图中有哪些常见DRC错误应该何解决。
    发表于 07-30 17:22 0次下载
    ORCAD原理图中有哪些常见DRC错误<b class='flag-5'>应该</b>如<b class='flag-5'>何解</b>决

    Access数据库不能写的问题应该何解决详细办法说明

    本文档的主要内容详细介绍的是Access数据库不能写的问题应该何解决详细办法说明。
    发表于 10-14 17:46 10次下载

    FPGA经常有哪些常见警告应该何解

    本文档的主要内容详细介绍的是FPGA经常有哪些常见警告应该何解决。
    发表于 10-14 16:00 9次下载
    FPGA经常有哪些常见警告<b class='flag-5'>应该</b>如<b class='flag-5'>何解</b>决

    使用FPGA经常会碰到哪些问题应该何解

    本文档的主要内容详细介绍的是使用FPGA经常会碰到哪些问题应该何解决。
    发表于 10-30 16:54 14次下载
    使用FPGA经常会<b class='flag-5'>碰到</b>哪些问题<b class='flag-5'>应该</b>如<b class='flag-5'>何解</b>决

    MySQL磁盘满了应该何解

    本文档的主要内容详细介绍的是MySQL磁盘满了应该何解决。
    发表于 12-26 10:25 2118次阅读

    C代码与javaScript函数的相互调用问题应该何解

    本文档的主要内容详细介绍的是C代码与javaScript函数的相互调用问题应该何解决。
    发表于 03-05 11:47 17次下载

    单片机初学者编程经常会碰到的问题及处理办法

    在刚开始接触单片机学习的时候,尤其是C语言基础比较薄弱的老铁们,经常会碰到很多比较低级的错误,程序编译错误一大堆,但不知道如何解决!一、程序
    发表于 11-13 14:51 9次下载
    单片机初学者编程经常会<b class='flag-5'>碰到</b>的问题及处理办法

    何解内存溢出

    ,有时候会自动关闭软件,重启电脑或者软件后释放掉一部分内存又可以正常运行该软件,而由系统配置、数据流、用户代码等原因而导致的内存溢出错误,即使用户重新执行任务依然无法避免 其实很简单,
    的头像 发表于 09-25 10:54 1381次阅读
    如<b class='flag-5'>何解</b>决<b class='flag-5'>内存</b>溢出

    何解内存碎片与内存交换效率慢的问题

    空间组合起来,是不是解决了这个问题?同样的,内存交换的时候我们保证交换的数据小,是不是能提高内存交换的效率? 这个办法就是内存分页,分页是把
    的头像 发表于 10-09 16:57 979次阅读
    如<b class='flag-5'>何解</b>决<b class='flag-5'>内存</b>碎片与<b class='flag-5'>内存</b>交换效率慢的问题