scikit-learn 并行,資源管理和配置

2023-02-20 14:49 更新

8.3.1. 并行計(jì)算

一些scikit-learn的評估器與實(shí)用程序可以通過多核CPU進(jìn)行并行計(jì)算,這要?dú)w功于下面的組件:

  • 通過 joblib 庫. 可以通過 n_jobs 參數(shù)控制程序的進(jìn)程或線程數(shù)量.
  • 通過OpenMP, 使用 C 或者 Cython 代碼.

此外,如果numpy安裝了特定的數(shù)字庫(如MKL、OpenBLAS或BLIS),scikit learn內(nèi)部使用的一些numpy例程也可以并行化。

我們將在下面的小節(jié)中描述這三個(gè)場景。

8.3.1.1. 基于Joblib的并行計(jì)算

當(dāng)?shù)讓訉?shí)現(xiàn)使用joblib時(shí),可以通過n_jobs參數(shù)來控制并行生成的worker(線程或進(jìn)程)的數(shù)量。

注意 在估計(jì)器中并行化發(fā)生的位置(和方式)目前文獻(xiàn)記錄不多。請幫助我們改進(jìn)我們的文檔并解決 issue 14228!

Joblib能夠同時(shí)支持多處理和多線程。joblib選擇生成線程還是進(jìn)程取決于它使用的后端。Scikit learn通常依賴于loky后端,這是joblib的默認(rèn)后端。Loky是一個(gè)多處理后端。

在進(jìn)行多進(jìn)程計(jì)算時(shí),為了避免在每個(gè)進(jìn)程中復(fù)制內(nèi)存(對于大數(shù)據(jù)集來說這是不合理的),joblib將創(chuàng)建一個(gè)memmap當(dāng)數(shù)據(jù)大于1MB時(shí),所有進(jìn)程都可以共享。

在某些特定情況下(當(dāng)并行運(yùn)行的代碼釋放GIL時(shí)),scikit learn將向joblib指示多線程后端是更可取的。

作為用戶,您可以通過使用上下文管理器來控制joblib將使用的后端(無論scikit learn推薦什么):

from joblib import parallel_backend

with parallel_backend('threading', n_jobs=2):
    # Your scikit-learn code here

有關(guān)更多詳細(xì)信息,請參閱joblib’s docs。

實(shí)際上,并行性運(yùn)算是否有助于改進(jìn)運(yùn)行時(shí)取決于許多因素。實(shí)驗(yàn)通常是一個(gè)好主意,而不是假設(shè)增加并行計(jì)算的數(shù)量總是一件好事。在某些情況下,并行運(yùn)行某些估計(jì)器或函數(shù)的多個(gè)副本會(huì)對性能造成極大的損害(請參閱下面的超額訂閱)。

8.3.1.2. 基于OpenMP的并行運(yùn)算

OpenMP使用Cython或C編寫的代碼實(shí)現(xiàn)并行化,完全依賴多線程。默認(rèn)情況下(除非joblib試圖避免超額使用)將使用盡可能多的線程。

您可以通過OMP-NUM-threads環(huán)境變量控制使用的線程的確切數(shù)量:

OMP_NUM_THREADS=4 python my_script.py

8.3.1.3. 基于特定數(shù)字庫的numpy并行化例程

Scikit learn在很大程度上依賴于NumPy和SciPy,后者在內(nèi)部調(diào)用在MKL、OpenBLAS或BLIS等庫中實(shí)現(xiàn)的多線程線性代數(shù)例程。

OpenBLAS、MKL或BLIS庫使用的線程數(shù)可以通過MKL_NUM_threadsOpenBLAS_NUM_threadsBLIS_NUM_threads環(huán)境變量設(shè)置。

請注意,scikit learn無法直接控制這些實(shí)現(xiàn)。Scikit-learn完全依賴于Numpy和Scipy

注意 在撰寫本文時(shí)(2019年),NumPy和SciPy軟件包在pypi.org網(wǎng)站(通過pip安裝)。conda forge通道上安裝的conda包與OpenBLAS鏈接,而從anaconda.org 默認(rèn)通道上安裝的conda包與MKL鏈接。

8.3.1.4. 過度消耗: 生成太多線程

通常建議避免使用比計(jì)算機(jī)上CPU數(shù)量多得多的進(jìn)程或線程。當(dāng)程序同時(shí)運(yùn)行太多線程時(shí),會(huì)發(fā)生過度消耗。

假設(shè)你有一臺(tái)有8個(gè)CPU的機(jī)器??紤]一種情況,在histgradientboostingcrifier(與OpenMP并行)上運(yùn)行GridSearchCV(與joblib并行)和n_jobs=8HistGradientBoostingClassifier的每個(gè)實(shí)例將產(chǎn)生8個(gè)線程(因?yàn)槟?個(gè)CPU)。總共有8*8=64個(gè)線程,這會(huì)導(dǎo)致物理CPU資源的超額訂閱和調(diào)度開銷。

使用嵌套在joblib調(diào)用中的MKL,OpenBLAS或BLIS的并行化例程,可以以完全相同的方式產(chǎn)生超額訂閱。

joblib>=0.14開始,當(dāng)使用oky后端(這是默認(rèn)值)時(shí),joblib將告訴其子進(jìn)程,以限制它們可以使用的線程數(shù),從而避免超額訂閱。在實(shí)踐中,joblib使用的啟發(fā)式方法是通過相應(yīng)的環(huán)境變量告訴進(jìn)程使用max_threads=n_cpu//n_jobs。回到上面的例子,由于GridSearchCV的joblib后端是loky,因此每個(gè)進(jìn)程只能使用1個(gè)線程而不是8個(gè)線程,從而減少了訂閱過多的問題。

注意:

  • 手動(dòng)設(shè)置其中一個(gè)環(huán)境變量(OMP NUM_THREADS、MKL NUM_THREADS、OPENBLAS NUM_THREADSBLIS NUM_THREADS)將優(yōu)先于joblib嘗試執(zhí)行的操作。線程總數(shù)將為n_jobs*_NUM_threads。請注意,設(shè)置此限制還將影響主進(jìn)程中的計(jì)算,該進(jìn)程只使用NUM線程。Joblib公開一個(gè)上下文管理器,以便更好地控制其工作線程的數(shù)量(請參閱下面鏈接的Joblib文檔)。

  • Joblib當(dāng)前無法避免多線程上下文中的超額訂閱。它只能使用“l(fā)oky”后端(它生成進(jìn)程)。

您將在joblib文檔中找到有關(guān)joblib緩解超額訂閱的其他詳細(xì)信息。

8.3.2. 配置開關(guān)

8.3.2.1. python 運(yùn)行時(shí)

sklearn.set_config 參數(shù)控制下列行為:

  • assume_finite(假設(shè)有限)

    用于跳過驗(yàn)證,這可以加快計(jì)算速度,但如果數(shù)據(jù)包含NaN,則可能導(dǎo)致分段錯(cuò)誤。

  • working_memory(工作內(nèi)存)

    一些算法使用的臨時(shí)數(shù)組的最佳大小。

8.3.2.2. 環(huán)境變量

在導(dǎo)入scikit-learn之前應(yīng)該先設(shè)置這些變量。

  • SKLEARN_SITE_JOBLIB

    當(dāng)此環(huán)境變量設(shè)置為非零值時(shí),scikit-learn使用站點(diǎn)joblib而不是其供應(yīng)商版本。因此,必須安裝joblib才能運(yùn)行scikit-learn。請注意,使用網(wǎng)站joblib需要您自擔(dān)風(fēng)險(xiǎn):scikit-learn和joblib的版本必須兼容。當(dāng)前,支持joblib 0.11+。此外,joblib.Memory的轉(zhuǎn)儲(chǔ)可能不兼容,您可能會(huì)丟失一些緩存并必須重新下載一些數(shù)據(jù)集。

    *從版本0.21開始不推薦使用:*從版本0.21開始,此參數(shù)無效,已刪除供應(yīng)商的joblib,并且始終使用站點(diǎn)joblib。

  • SKLEARN_ASSUME_FINITE

    assume_finite參數(shù) 設(shè)置默認(rèn)值 sklearn.set_config.

  • SKLEARN_WORKING_MEMORY

    working_memory參數(shù) 設(shè)置默認(rèn)值 sklearn.set_config.

  • SKLEARN_SEED

    為了運(yùn)行可重復(fù)性,在運(yùn)行測試時(shí)設(shè)置全局隨機(jī)數(shù)生成器的種子。

  • SKLEARN_SKIP_NETWORK_TESTS

    當(dāng)此環(huán)境變量設(shè)置為非零值時(shí),將跳過需要網(wǎng)絡(luò)訪問的測試。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號