我正在嘗試訓練多個“檔案”(這里主要是日志格式),如果我指定多個核心(我有),Doc2Vec 需要更長的時間。
我的資料如下所示:
print(len(train_corpus))
7930196
print(train_corpus[:5])
[TaggedDocument(words=['port', 'ssh'], tags=[0]),
TaggedDocument(words=['session', 'initialize', 'by', 'client'], tags=[1]),
TaggedDocument(words=['dfs', 'fsnamesystem', 'block', 'namesystem', 'addstoredblock', 'blockmap', 'update', 'be', 'to', 'blk', 'size'], tags=[2]),
TaggedDocument(words=['appl', 'selfupdate', 'component', 'amd', 'microsoft', 'windows', 'kernel', 'none', 'elevation', 'lower', 'version', 'revision', 'holder'], tags=[3]),
TaggedDocument(words=['ramfs', 'tclass', 'blk', 'file'], tags=[4])]
我有 8 個內核可用:
print(os.cpu_count())
8
我在 Centos7 上使用 gensim 4.1.2。使用這個方法(stackoverflow.com/a/37190672/130288),看起來我的 BLAS 庫是 OpenBlas,所以我在我的 bashrc 上設定了 OPENBLAS_NUM_THREADS=1(并且可以從 Jupyter 中看到,使用 !echo $OPENBLAS_NUM_THREADS=1 )
這是我的測驗代碼:
dict_time_workers = dict()
for workers in range(1, 9):
model = Doc2Vec(vector_size=20,
min_count=1,
workers=workers,
epochs=1)
model.build_vocab(train_corpus, update = False)
t1 = time.time()
model.train(train_corpus, epochs=1, total_examples=model.corpus_count)
dict_time_workers[workers] = time.time() - t1
變數dict_time_workers也相等:
{1: 224.23211407661438,
2: 273.408652305603,
3: 313.1667754650116,
4: 331.1840877532959,
5: 433.83785605430603,
6: 545.671571969986,
7: 551.6248495578766,
8: 548.430994272232}
正如你所看到的,所花費的時間是增加而不是減少。結果似乎與更大的時期引數相同。除了這個,我的 Centos7 上什么都沒有運行。
如果我使用htop查看執行緒上發生的情況,我會發現每次訓練都使用了正確數量的執行緒。但是,使用的執行緒越多,使用百分比就越低(例如,只有一個執行緒,使用了 95%,對于 2,它們都使用了大約 65% 的最大功率,對于 6 個執行緒是 20-25% 。 ..)。我懷疑是 IO 問題,但iotop向我展示了同一個磁盤上沒有發生任何不好的事情。
這篇文章現在似乎與這篇文章 沒有效率地使用多核 CPU 來訓練 Doc2vec 和 gensim 相關。
uj5u.com熱心網友回復:
如果從這樣的額外內核中得不到任何好處,您安裝的 BLAS 庫很可能已經配置為嘗試將所有內核用于每個批量陣列操作。這意味著其他嘗試使用更多內核(如 Gensim 的workers規范)只會增加爭用的開銷,因為每個單獨的作業執行緒的單獨 BLAS 標注也嘗試使用 8 個執行緒。
根據使用的 BLAS 庫,它自己使用更多內核的傾向通常會受到環境變數的限制,例如OPENBLAS_NUM_THREADS和/或MKL_NUM_THREADS。
如果您1在行程啟動之前將這些設定為,您可能會看到不同的,并且可能更好的多執行緒行為。
但請注意:1只是恢復了每個作業執行緒只使用單個內核的假設。BLAS-cores 和 Gensim-worker-threads 的其他一些組合實際上可能實作最佳的訓練吞吐量和非競爭性核心利用率。
而且,至少對于 Gensim 而言workers,實作最佳吞吐量的實際執行緒計數值將根據其他模型引數而變化,這些引數會影響高度可并行化代碼塊與高度競爭塊中計算時間的相對量,尤其是window, vector_size, & negative。而且,除了通過反復試驗之外,沒有真正找到最佳workers價值的捷徑:在運行幾分鐘后觀察日志中報告的訓練率。(不過:在簡短的試運行的 2-4 分鐘內觀察到的任何速率都應該代表多個時期內整個語料庫的訓練速率。)
(對于任何至少有 4 個核心的系統,經典可迭代語料庫的最佳值TaggedDocuments通常至少為 3,不超過核心數,但也很少超過 8-12 個執行緒,因為其他固有的爭用來源由于 Gensim 在作業執行緒之間展開作業的方法以及 Python 的“GIL”。)
其他想法:
- 該
build_vocab()步驟永遠不會是多執行緒的,因此對替代值進行基準測驗將通過僅對步驟workers進行計時來更真實地讀出它們的效果train() - 確保您的可迭代語料庫在每次通過時做盡可能少的冗余作業(比如 IO 和標記化)可以幫助限制圍繞單個管理器執行緒執行每個時期的迭代和批處理文本給作業人員的任何瓶頸
- 替代
corpus_file方法可以通過為每個執行緒分配其自己的輸入檔案專有范圍來實作更高的核心利用率,多達任意數量的核心。但是,這也意味著 (a) 你的整個語料庫必須在一個未壓縮的空間標記純文本檔案中;(b) 你的檔案只得到一個整數tag(他們的行號);(c) 您可能會遇到一些尚未診斷和修復的小錯誤。(參見專案問題 #2747。)
uj5u.com熱心網友回復:
好的,充分利用核心的最好方法是使用doc2vec的引數corpus_file。
做同樣的板凳,結果如下:
{1: 114.58889961242676, 2: 82.8250150680542, 3: 71.52109575271606, 4: 67.1010684967041, 5: 75.96869373321533, 6: 100.68377351760864, 7: 116.7901406288147, 8: 139.53436756134033}
該執行緒似乎很有用,在我的情況下 4 是最好的。仍然奇怪的是,“常規” doc2vec 在并行化方面并不出色
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/526400.html
