Python高效計(jì)算庫Joblib的入門教程
1. Joblib庫是什么?
Joblib
是一個(gè)用于在 Python 中進(jìn)行高效計(jì)算的開源庫,提供了一些用于內(nèi)存映射和并行計(jì)算的工具,能大幅提高科學(xué)計(jì)算和數(shù)據(jù)分析的效率,特別適合于需要進(jìn)行重復(fù)計(jì)算或大規(guī)模數(shù)據(jù)處理的任務(wù)。
Joblib 庫的常用關(guān)鍵功能包括對(duì)象高效序列化、函數(shù)值臨時(shí)緩存以及并行計(jì)算,能夠優(yōu)化數(shù)據(jù)處理流程。在Python中安裝 Joblib 庫也非常簡單,通過 pip 執(zhí)行以下命令即可:
pip install joblib
安裝完成后,執(zhí)行如下代碼,如果能輸出相應(yīng)版本號(hào),則說明已經(jīng)成功安裝。
import joblib print(joblib.__version__)
2. 核心功能介紹及演示
joblib
庫的主要功能體現(xiàn)在以下三方面:
- 高效序列化和反序列化:除特殊Python對(duì)象外,Joblib 庫能將數(shù)值對(duì)象高效序列化保存到本地,常常用來保存、加載數(shù)據(jù)對(duì)象和模型對(duì)象;
- 快速磁盤緩存:夠提供高效的磁盤緩存和延遲加載,可以將函數(shù)的返回值緩存到磁盤上以避免重復(fù)計(jì)算;
- 并行計(jì)算:能輕松將代碼任務(wù)分配到多核處理器上。
2.1 高效序列化和反序列化對(duì)象
類似于 pickle 庫,Joblib 庫提供了 dump
和 load
函數(shù),能夠高效地將大型數(shù)據(jù)對(duì)象(例如大型數(shù)組、機(jī)器學(xué)習(xí)模型等)保存到本地文件或從本地文件加載回來。Joblib 針對(duì) numpy 數(shù)組進(jìn)行了特定的優(yōu)化,基于殊序列化格式,相比于通用的序列化更加高效。
如下例子,對(duì)比了 pickle 庫和 Joblib 庫在保存和加載大規(guī)模數(shù)組上的效率。首先生成 ( 10000 , 10000 ) (10000,10000)(10000,10000) 的數(shù)組,兩個(gè)庫分別循環(huán)保存和加載數(shù)據(jù) 5 55 次,最終的平均處理時(shí)間如下(見注釋部分):
import numpy as np import pickle, joblib, time # 生成一個(gè)大型的 numpy 數(shù)組對(duì)象,例如 10000 x 10000 的數(shù)組 large_array = np.random.rand(10000, 10000) # 循環(huán)5次 n = 5 # 平均處理時(shí)間 2.54s for i in range(n): with open(f'pickle_data_{i}.pkl', 'wb') as f: pickle.dump(large_array, f) # 平均處理時(shí)間 0.72s for i in range(n): with open(f'pickle_data_{i}.pkl', 'rb') as f: load_large_array = pickle.load(f) # 平均處理時(shí)間 2.16s for i in range(n): joblib.dump(large_array, f'joblib_data_{i}.joblib') # 平均處理時(shí)間 0.04s for i in range(n): load2_large_array = joblib.load(f'joblib_data_{i}.joblib')
相比于 pickle 庫加載 .pkl
文件,Joblib 庫加載 .joblib
文件的平均效率極高,保存文件的效率也有一定的優(yōu)勢(shì),此外,Joblib 庫的接口更加易用,因此在處理含大量數(shù)據(jù)的任務(wù)時(shí)常常用來代替 pickle 庫。
這種保存再加載的方式,常用在將訓(xùn)練好的模型或計(jì)算的數(shù)據(jù)集保存后分發(fā)給其他用戶,還常常用于大規(guī)模數(shù)據(jù)的深拷貝(相比于直接深拷貝,保存后加載的方式常常更快)等場(chǎng)景中。
2.2 快速磁盤緩存
Joblib 庫的另一核心功能是能將函數(shù)的計(jì)算返回值快速緩存到磁盤上(記憶模式),當(dāng)再次調(diào)用該函數(shù)時(shí),如果函數(shù)的輸入?yún)?shù)沒有改變,則 Joblib 直接從緩存中加載結(jié)果而不是重新計(jì)算。
如下例子,通過定義緩存目錄,以及創(chuàng)建緩存器,添加指定裝飾器后,當(dāng)我們運(yùn)行第一次函數(shù)時(shí),會(huì)將函數(shù)計(jì)算結(jié)果緩存到磁盤,再次調(diào)用函數(shù)時(shí),如果輸入?yún)?shù)相同,則從磁盤調(diào)出相應(yīng)的計(jì)算結(jié)果,避免重復(fù)計(jì)算。當(dāng)然了,很自然的一個(gè)想法是,為什么不把函數(shù)的計(jì)算結(jié)果保存為哈希表,傳入?yún)?shù)為鍵,計(jì)算結(jié)果為值,當(dāng)然也是可行的,但這會(huì)極大占用內(nèi)存,而 Joblib 是將原本應(yīng)在內(nèi)存上的計(jì)算結(jié)果緩存到磁盤,且緩存和調(diào)用的處理非常快。
from joblib import Memory import time cachedir = './my_cache' # 定義緩存目錄 memory = Memory(cachedir, verbose=0) @memory.cache def expensive_computation(a, b): print("Computing expensive_computation...") sum_ = 0 for i in range(1000000): sum_ += a * b / 10 + a / b return sum_ # 第一次調(diào)用,將計(jì)算并緩存結(jié)果 result = expensive_computation(20, 3) # 0.0967 s # 第二次調(diào)用,將直接從緩存加載結(jié)果 result = expensive_computation(20, 3) # 0.000997 s
上述代碼的裝飾器可以理解為將函數(shù) expensive_computation 作為參數(shù)傳入 memory.cache() 方法當(dāng)中,上述寫法等價(jià)于 memory.cache(expensive_computation())。
顯然,對(duì)于有大量重復(fù)計(jì)算的任務(wù),該庫能極大地提高處理效率。值得注意的是,上述定義的函數(shù)中,存在打印語句 print(...)
,當(dāng)首次執(zhí)行函數(shù)時(shí),會(huì)執(zhí)行該打印語句,而函數(shù)是重復(fù)執(zhí)行的,則會(huì)直接從緩存中繼承曾經(jīng)的計(jì)算結(jié)果,而不會(huì)經(jīng)過中間具體的計(jì)算邏輯,也就不會(huì)打印相關(guān)語句。
2.3 并行計(jì)算
Joblib 的最核心的功能應(yīng)該是提供了高級(jí)的(簡單易用)并行化工具,能夠使我們輕松地將計(jì)算任務(wù)分配到多個(gè) CPU 核心上執(zhí)行。
如下所示,當(dāng)我們有多個(gè)獨(dú)立的任務(wù)需要執(zhí)行,可以通過 Joblib 的 Parallel
和 delayed
功能并行處理這些任務(wù),從而節(jié)省時(shí)間。
from joblib import Parallel, delayed import numpy as np def process(i): data = np.random.rand(1000, 1000) # 普通的循環(huán)計(jì)算 # 5.798 s for i in range(1000): process(i) # Joblib 的并行計(jì)算 # 3.237 s Parallel(n_jobs=4)(delayed(process)(i) for i in range(1000))
上述式子在,n_jobs
定義了線程數(shù),若n_jobs=-1
,則啟用所有可用的 CPU 核心;delayed()
中傳入任務(wù)(函數(shù))名,而后的 (i)
為任務(wù)分配傳入?yún)?shù),在 Joblib 的并行計(jì)算下,執(zhí)行 1000 10001000 次任務(wù) process()
的時(shí)間為 3.237 s 3.237s3.237s,而循環(huán)依次執(zhí)行的時(shí)間為 5.798 s 5.798s5.798s。
隨著任務(wù)的計(jì)算復(fù)雜度增大、獨(dú)立任務(wù)數(shù)增多,并行計(jì)算的優(yōu)勢(shì)會(huì)逐漸明顯,但相對(duì)于我們開的并行任務(wù)數(shù),這種優(yōu)勢(shì)有時(shí)并不那么顯著。原因在于,默認(rèn)情況下,joblib.Parallel
是啟動(dòng)單獨(dú)的Python工作進(jìn)程,以便在分散的CPU上同時(shí)執(zhí)行任務(wù),但由于輸入和輸出數(shù)據(jù)需要在隊(duì)列中序列化以便同工作進(jìn)程進(jìn)行通信,可能會(huì)導(dǎo)致大量開銷。因此,小規(guī)模任務(wù)下,Joblib 的并行計(jì)算效率可能較低。
到此這篇關(guān)于Python高效計(jì)算庫Joblib的入門教程的文章就介紹到這了,更多相關(guān)Python高效計(jì)算庫Joblib內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python編寫繪圖系統(tǒng)之從文本文件導(dǎo)入數(shù)據(jù)并繪圖
這篇文章主要為大家詳細(xì)介紹了Python如何編寫一個(gè)繪圖系統(tǒng),可以實(shí)現(xiàn)從文本文件導(dǎo)入數(shù)據(jù)并繪圖,文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-08-08python飛機(jī)大戰(zhàn)游戲?qū)嵗v解
在本篇文章里小編給大家整理的是一篇關(guān)于python飛機(jī)大戰(zhàn)游戲?qū)嵗v解,有興趣的朋友們可以參考下。2020-12-12深入淺出Python中三個(gè)圖像增強(qiáng)庫的使用
這篇文章主要帶大家了解一下Python中三個(gè)圖像增強(qiáng)庫的使用:Imgaug、Albumentations和SOLT,文中通過示例進(jìn)行了詳細(xì)介紹,需要的可以參考一下2022-05-05Centos 升級(jí)到python3后pip 無法使用的解決方法
今天小編就為大家分享一篇Centos 升級(jí)到python3后pip 無法使用的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-06-06