當(dāng)你寫了一個(gè)處理數(shù)據(jù)的軟件,它可能在小樣本文件上運(yùn)行地很好,但一旦加載大量真實(shí)數(shù)據(jù)后,這個(gè)軟件就會(huì)崩潰。
問題在于你沒有足夠的內(nèi)存——如果你有 16GB 的 RAM ,你就無法一次載入 100GB 大小的文件。載入這么大的文件時(shí),操作系統(tǒng)在某個(gè)時(shí)刻就會(huì)耗盡內(nèi)存,不能分配存儲(chǔ)單元,你的程序也就會(huì)崩潰。
所以,你該怎樣防止這類情況發(fā)生?你可以啟動(dòng)一個(gè)大數(shù)據(jù)集群——你所需要做的是:
搞到一個(gè)計(jì)算機(jī)集群。
花一周時(shí)間搭建這個(gè)集群。
大部分情況下,你需要學(xué)習(xí)一套全新的 API,重寫你所有的代碼。
這個(gè)代價(jià)可能很昂貴,會(huì)令人沮喪;幸運(yùn)的是,大部分情況下,我們不必這樣做。
你需要一個(gè)簡單而容易的解決方案:在單機(jī)上處理你的數(shù)據(jù),最小化環(huán)境搭建開銷,盡可能利用你正在使用的代碼庫。實(shí)際上,大部分情況你都可以做到這樣,只要使用一些方法即可,有時(shí)候這些方法被稱為“核外計(jì)算”(out-of-core computation)。
本文將介紹如下內(nèi)容:
你究竟為什么需要 RAM。
處理無法放入內(nèi)存的數(shù)據(jù)最簡單的方法:花些錢。
處理大量數(shù)據(jù)的三種基本軟件方法:壓縮、分塊、索引。
之后的文章將會(huì)展示如何把這些方法應(yīng)用到諸如 NumPy 和 Pandas 這樣的庫中。
1你究竟為什么需要 RAM?
在我們開始解釋解決方案前,我們要弄清楚該問題是如何產(chǎn)生的。我們的計(jì)算機(jī)內(nèi)存(RAM)能讓你讀寫數(shù)據(jù),但是你的硬盤也可以讀寫數(shù)據(jù)——那為什么計(jì)算機(jī)還需要 RAM 呢?硬盤比 RAM 更便宜,所以它通常大到能夠容納下你的所有數(shù)據(jù),那為什么你的代碼不能直接從硬盤讀寫數(shù)據(jù)呢?
理論上講,這也行得通的。但是,即使是最現(xiàn)代化且速度很快的 SSD 硬盤也比 RAM 慢太多:
從 SSD 上讀取數(shù)據(jù): 大約 1.6 萬納秒
從 RAM 上讀取數(shù)據(jù): 大于 100 納秒
如果你想要實(shí)現(xiàn)快速計(jì)算,數(shù)據(jù)就只能放在 RAM 中,否則你的代碼運(yùn)行時(shí)就會(huì)慢上 150 倍。
2資金方面的解決方案:購買更多的 RAM
沒有足夠 RAM 時(shí)的最簡單解決方案就是花錢來解決。你要么購買一臺(tái)計(jì)算機(jī),或者租一臺(tái)云端的虛擬機(jī)(VM:Virtual Machine,這會(huì)比大多數(shù)筆記本電腦貴得多)。2019 年 11 月,我稍微調(diào)研了一下,在價(jià)格方面做了一些比較,發(fā)現(xiàn)你可以這樣:
購買 一臺(tái) Thinkpad M720 Tower,它有 6 個(gè)核和 64GB RAM,價(jià)格是 1074 美金。
租用 一臺(tái)云端的 VM,它有 64 個(gè)核和 432GB RAM,價(jià)格是每小時(shí) 3.62 美金。
這只是我稍微調(diào)研后發(fā)現(xiàn)的數(shù)字,再繼續(xù)調(diào)研下去,你會(huì)發(fā)現(xiàn)更好的方案。
如果花錢購買硬件可以把你的數(shù)據(jù)讀入 RAM,這通常就會(huì)是一個(gè)最經(jīng)濟(jì)的解決方案:畢竟你的時(shí)間相當(dāng)寶貴。但是,有時(shí)候,這還不夠解決這個(gè)問題。
例如,如果你要運(yùn)行許多數(shù)據(jù)處理任務(wù),在一段時(shí)期內(nèi),云計(jì)算可能是一個(gè)自然能想到的解決方案,但也是一個(gè)昂貴的解決方案。曾經(jīng)在一個(gè)工作中,我的軟件項(xiàng)目需要的計(jì)算開銷幾乎快用完了我們產(chǎn)品所有的預(yù)期收入,包括支付我薪水所需的至關(guān)重要的那部分收入。
如果購買 / 租用更多的 RAM 不足以滿足需求或者根本行不通時(shí),下一步就應(yīng)該考慮如何通過修改軟件來減少內(nèi)存使用了。
3技巧 #1:壓縮
壓縮意味著用一種不同的表達(dá)形式表示你的數(shù)據(jù),這種形式能占用更少內(nèi)存。有兩種方式來壓縮:
無損壓縮: 存儲(chǔ)的數(shù)據(jù)包含的信息和原始數(shù)據(jù)包含的信息完全相同。
有損壓縮: 存儲(chǔ)的數(shù)據(jù)丟失了一些原始數(shù)據(jù)里的細(xì)節(jié)信息,但是這種信息丟失理想情況下不會(huì)對(duì)計(jì)算結(jié)果造成什么影響。
我想說明的是,我不是在談?wù)撌褂?ZIP 或者 gzip 工具來壓縮文件,因?yàn)檫@些工具通常是對(duì)硬盤上的文件進(jìn)行壓縮的。為了處理 ZIP 壓縮過的文件,你通常需要把這個(gè)文件載入內(nèi)存中再進(jìn)行解壓縮為原始文件大小,所以這其實(shí)對(duì)內(nèi)存節(jié)省沒有什么幫助。
你需要的是內(nèi)存中的數(shù)據(jù)壓縮表示形式。
例如,比如說你的數(shù)據(jù)有兩個(gè)值,一共也只會(huì)有兩個(gè)值:“AVAILABLE”(代表可能取到的值)和“UNAVAILABLE”(代表不可能取到的值)。我們可以不必將其存為 10 個(gè)或更多字節(jié)的字符串,你可以將其存為一個(gè)布爾值,用 True 或者 False 表示,這樣你就可以只用 1 個(gè)字節(jié)來表示了。你甚至可以繼續(xù)壓縮至 1 位來表示布爾值,這樣就繼續(xù)壓縮到了 1 個(gè)字節(jié)時(shí)的 1/8 大小。
4技巧 #2:分塊,每次只加載所有數(shù)據(jù)里的某一塊
當(dāng)你需要處理所有數(shù)據(jù),而又無需把所有數(shù)據(jù)同時(shí)載入內(nèi)存時(shí),分塊是很有用的。你可以把數(shù)據(jù)按塊載入內(nèi)存,每次計(jì)算一塊的數(shù)據(jù)(或者正如我們要在今后一篇文章里想討論的,可以多塊并行處理)。
例如,比如說,你想搜索一本書里的最長單詞。你可以一次性將所有數(shù)據(jù)載入內(nèi)存:
largest_word = “” for word in book.get_text.split: if len(word) 》 len(largest_word):largest_word = word
但是在我們的例子中,這本書太大而不能完全載入內(nèi)存,這時(shí)候你就可以一頁一頁地載入這本書。
largest_word = “” for page in book.iterpages: for word in page.get_text.split: if len(word) 》 len(largest_word): largest_word = word
這樣你使用的內(nèi)存就大大減少了,因?yàn)槟阋淮沃恍枰堰@本書的一頁載入內(nèi)存,而最后得到的結(jié)果仍然是正確的。
5技巧 #3:當(dāng)你需要數(shù)據(jù)的一個(gè)子集時(shí),索引會(huì)很有用
當(dāng)你需要數(shù)據(jù)的一個(gè)子集時(shí),索引會(huì)很有用,使用索引你可以在不同時(shí)刻加載數(shù)據(jù)的不同子集。
你也可以用分塊解決這個(gè)問題:每次加載所有的數(shù)據(jù),過濾掉你不想要的數(shù)據(jù)。但這會(huì)很慢,因?yàn)槟慵虞d了很多不相關(guān)的數(shù)據(jù)。
如果你只需要部分?jǐn)?shù)據(jù),不要使用分塊,最好使用索引,它可以告訴你到哪里能找出你關(guān)心的那部分?jǐn)?shù)據(jù)。
想象一下,你只想閱讀書本中關(guān)于土豚的章節(jié)。如果你運(yùn)用分塊技術(shù),你得載入整本書,一頁一頁的載入,每頁地搜尋土豚——但這要花很長時(shí)間才能完成。
或者說,你可以直接閱讀這本書的末尾部分,也就是書本的索引部分,然后找到“土豚”的索引項(xiàng)。它可能會(huì)告訴你在第 7、19 頁以及 120-123 頁可以讀到相關(guān)內(nèi)容。所以,現(xiàn)在你可以只讀那幾頁,這樣就快多了。
這樣很有效,因?yàn)樗饕日緯加玫目臻g要小很多,所以把索引載入內(nèi)存找出相關(guān)內(nèi)容所在就會(huì)更容易。
6最簡單的索引技巧
最簡單也最常用的實(shí)現(xiàn)索引的方法就是在目錄里給文件恰當(dāng)命名:
mydata/ 2019-Jan.csv 2019-Feb.csv 2019-Mar.csv 2019-Apr.csv 。..
如果你想要 2019 年 3 月數(shù)據(jù),你就只需要加載 2019-Mar.csv 這個(gè)文件——而不用加載 2 月、7 月或者其他任何月份的數(shù)據(jù)。
7下一步:應(yīng)用這些技巧
RAM 不夠用,最簡單的解決方法就是花錢買更多的 RAM。但是,如果這個(gè)方案無法實(shí)現(xiàn)或者仍然不夠用時(shí),你就需要使用壓縮、分塊或者索引來解決。
這些方法也出現(xiàn)在其他許多不同的軟件包和工具中。即使是大數(shù)據(jù)系統(tǒng)也是建立在這些方法之上的:例如使用多個(gè)計(jì)算機(jī)來處理分塊數(shù)據(jù)。
在接下來的文章里,我會(huì)給你展示如何使用具體的庫和工具(NumPy、Pandas,或者用 ZIP 工具壓縮文件)來應(yīng)用這些方法。如果在我寫完這些文章時(shí),你就想閱讀到它們,請(qǐng)?jiān)谙路奖砀窭镒?cè)我的通訊簡報(bào)(newsletter)。
-
RAM
+關(guān)注
關(guān)注
8文章
1369瀏覽量
114826 -
程序
+關(guān)注
關(guān)注
117文章
3793瀏覽量
81227 -
大數(shù)據(jù)
+關(guān)注
關(guān)注
64文章
8900瀏覽量
137585
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論