質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

10107閲覧

pythonのmultiprocessingを利用しているがCPU使用率があまり上がっていない

kohekoh

総合スコア140

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2017/07/24 12:16

編集2017/07/24 13:28

タイトル通りです

pythonのmultiprocessingを利用して、並列処理を行っていますが
タスクマネージャを見ると、CPU使用率があまり上がっていません
CPUを最大限に使うようなコードを書いています
例えば

python

1p = Pool() 2p = Pool(multiprocessing.count()) 3p = Pool(8) #仮想コアが8のため

これらを試しましたが、CPUはあまり変化しません
コードに何か問題があるのか
他に何か考えられることはありますか?

python

1import nltk 2import numpy as np 3import json 4import nltk_exa as nl 5import time 6from multiprocessing import Pool 7#import multiprocessing 8import sys 9 10def subcalc(word): 11 subdoc = [] 12 lists = [] 13 collection = nltk.TextCollection(word) #サイトにのっていた 14 #uniqterms = list(set(collection)) #ここも上と同じサイトに載っていた 15 wo=[] 16 for term in set(word): 17 if(collection.tf_idf(term, word) > 0): 18 wo.append([term,collection.tf_idf(term, word)]) #ここも上のサイトにのってる 19 #print(wo) 20 wo.sort(key=lambda x:x[1]) #keyに無名関数lambdaをいれてる woの1番目の要素(WO(1,2)だったら”2”)でソート 21 wo.reverse() 22 try: 23 slice1 = np.array(wo[:20]) #先頭の文字から終了インデックスまでが抽出 24 lists = slice1[:,0] #[:]は戦闘から終了のインデックスまで抽出と、slice1の0番目を格納 25 subdoc.append(list(lists)) #listsが文字列だから、リストに格納 26 del wo 27 except: 28 print(wo) 29 return subdoc 30 31def tfidf(): 32 t1 = time.time() 33 doc0 = [] 34 doc = [] 35 word0 = [] 36 word = [] 37 f = open("/Users//Dropbox/prg/dataset/word0_notuseful012.txt") 38 for row in f: 39 word0.append(row.split("][")) 40 f.close() 41 for i in word0[0]: 42 word.append(str(i).replace("[","").replace("]","").replace(",","").replace("'","").replace("\"","").split()) 43 #word.pop() 44 ttt = time.time() 45 p = Pool(4) 46 #a = subcalc(word) #1コアによる実行 47 #print(a) 48 doc = p.map(subcalc, word) #複数コアによる実行 49 t3 = time.time() 50 #print(doc[0][0]) 51 #print('processing time(nltkはこんだけかかってる)(終わり): ' + str(ttt - tt) + '(sec)') 52 print('processing time2(終わり): ' + str(t3 - ttt) + '(sec)') 53 54if __name__ == "__main__": 55 tfidf()

ちなみにこのテキストファイルは30万行ほどのテキストファイルです
このときCPU使用率は40%ほどです

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quickquip

2017/07/24 13:09

「CPUを最大限に使うようなコードじゃない」か「並列処理をしていない」かのどちらかだと思いますが。Poolを作っている部分だけじゃなにもわからないでしょう。使っている部分のソースがなければ誰も判断できないですよねね。
kohekoh

2017/07/24 13:19

CPUを最大限に使うようなコードじゃないということもあるのですね、それを知ることができたのでよかったです、おそらくそれだと思うのですが、どうですか
quickquip

2017/07/25 13:11 編集

30万行あっても最初の1行しか処理してないから実質1プロセスしか仕事していないように見えます。←訂正します。すみません。1行目がとても大きくて4件以上分のデータが入っているのなら問題ないのですがそういうことでしょうか。
quickquip

2017/07/25 13:11

あと、subcalcがTF-IDFを計算しているように見えないことも気になりました。これはTFだけ計算させているのでしょうか?
kohekoh

2017/07/25 14:13

一行目に4件以上分のデータが入るというのはどういう状況でしょうか、ちなみに、タスクマネージャをみるとスレッドが増えているので複数プロセスで動いてそうです
kohekoh

2017/07/25 14:14

TFIDFをやっているつもりです、ここが間違っているとちょっとつらいですね…
quickquip

2017/07/25 14:27

単にコードの転記間違いかと思ったのですが。
guest

回答1

0

ベストアンサー

スレッドじゃなくてプロセスだとは思いますが「プロセスが増えている」ことはなんの保証にもなりません。何もしていないプロセスが待機しているだけなのでしょう。

これを実行するとわかります。1つのプロセスだけ60秒sleepする処理が実行されるけれども、他の9プロセスは存在するけれども正真正銘何もしていないです。

import time from multiprocessing import Pool def wait(sec): print('wait executed') time.sleep(sec) def main(): Pool(10).map(wait, [60]) if __name__ == "__main__": main()
f = open("/Users//Dropbox/prg/dataset/word0_notuseful012.txt") for row in f: word0.append(row.split("]["))

でrowに行を読みこみますね。

for i in word0[0]: word.append(str(i).replace("[","").replace("]","").replace(",","").replace("'","").replace("\"","").split())

1行目row.split("][")した結果の分、ループしていますね。
word.appendは1回しかやっていないので、wordの要素数は「1行目をrow.split("][")した結果」の個数に等しいです。
それをPool.mapに渡していますから、「1行目をrow.split("][")した結果」が1つより多ければ複数プロセスで回りますが、そうでなければプロセスは1つだけ実行されていて、他のプロセスは待機しているだけですね。

ところで、wordは「strを要素にしたlist」のlistですね。(型アノテーション的に書くとList[List[str]])

だから

def subcalc(word):

に渡るwordは「strを要素にしたlist」なのでドキュメント1個分の情報しかないように見えます。
これではidfは計算しできない(しても意味が無い)ですね。

投稿2017/07/25 14:45

編集2017/07/26 00:50
quickquip

総合スコア11038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kohekoh

2017/07/25 17:43

一行目には40ほど文字列があるので大丈夫だと思います tfidfについての知識が浅いので、もっと勉強します リストを2個以上わたさないと計算できないということですか?
quickquip

2017/07/26 01:21 編集

word(単語)がたくさん集まってtext(文書)になって、text(文書)がたくさん集まってtext collection(文書集合)になります。 TF-IDFのうち、IDFの方は文書集合に定義されるものなので、nltk.TextCollection を作るときの引数は「『strのlist』のlist」を(普通)とります。nltk.TextCollection([['a','b','c'],['b','c','d'],['c','e']]) みたいに。
kohekoh

2017/07/26 03:05

なるほど… ということはwordは [[['a','b','c'],['b','c','d'],['c','e']]] このようにならないといけないということですかね?
kohekoh

2017/07/26 03:34

doc = p.subcalc(word) こういうこともできないですよね?
quickquip

2017/07/26 05:18

pool.mapに渡したいならwordの形はそうですけど、マルチプロセスにはなりませんね.
kohekoh

2017/07/26 05:43

理解があってるかわからないのですが idfをするときはリストに3つの要素(リスト)があったら、 1つの要素を他の3つと比較する作業ということですよね ということは、一つ目の要素を回すのに1つのプロセスを使って 二つ目の要素を回すのに2つ目のプロセスを使って… という風にマルチプロセスにならないのですか?
quickquip

2017/07/26 06:07

[[['a','b','c'],['b','c','d'],['c','e']]] は1つしか要素を持っていませんよ。 idfの計算を自分で作るなら、そういう風に「マルチプロセスで処理するように書く」ことはできるでしょう。
kohekoh

2017/07/26 06:14

word自体の要素は1つですが、mapを用いたときは nltk.TextCollection([['a','b','c'],['b','c','d'],['c','e']]) のように渡されますよね ということは要素は3つだと思うのですが、違いますか?
kohekoh

2017/07/26 06:38 編集

そもそもおもったのですが、 collection = nltk.TextCollection(word) この処理をsubcalcに入る前に計算させて、 doc = p.map(subcalc, word, collection) このようにすればいいのではと思ったのですが、どうですか ちなみに doc = p.map(subcalc, word, collection) のときにエラーが出ます unorderable types: textcollection() <= int()
quickquip

2017/07/26 07:00

あなたがそう思っても multiprocessing.pool.Pool はそうは動かない。
kohekoh

2017/07/26 07:03

どうすればいいんですかね
quickquip

2017/07/26 07:05

word自体の要素が1つならmultiprocessing.pool.Poolは1のプロセスでしか処理しない。 このようにすればいいのではとあなたがどう思おうとも、multiprocessing.pool.Poolはそのように渡したら動かない。 どうですかと聞かれても、あなたがmultiprocessing.pool.Poolを使おうと思った問題がそれで解決するならいいし、解決しないなら駄目でしょう、としか私には答えられない。
quickquip

2017/07/26 07:11

multiprocessing.pool.Poolを使ってTF-IDFの計算の中のどの部分の処理を並列化したかったのか? というのが伝わっていないです。(なぜなら質問のソースは並列になってないから)
kohekoh

2017/07/26 07:35

自分がいまいちmutiprocessingの使い方がわかっていないみたいなのですが 自分はtfidfの処理全体を並列化したつもりでした とりあえず動かして、動くので 並列化もtfidfもできていると思っていました
quickquip

2017/07/26 07:36

nltk.TextCollectionを作成するのがあまり時間がかからなくて、そのなかの処理が**ループ回数が多すぎて**時間がかかるようなら、nltk.TextCollectionを作成してしまってその後をマルチプロセスで実行するのはいいと思います。本当にそういう状況なのかはわかりません。
kohekoh

2017/07/26 07:46

collection = nltk.TextCollection(word) これを先にするということですよね となると unorderable types: textcollection() <= int() のエラーが出てしまいます これは nltk.TextCollectionの計算の中で textcollection() <= int()をやってしまっているということでいいんですかね
kohekoh

2017/07/26 08:23

普通のmapと勘違いしていました ありがとうございます
kohekoh

2017/07/26 12:29

動かしてみたところ、結局 普通の処理よりも遅くなってしまいました これは、wordに一つの要素しか入ってないことに起因しているということですか? 自分の思っているmultiproceddingの動作は subcalcを複数のプロセスで呼び出すとおもっているのですが そういうことではないということですよね?
quickquip

2017/07/26 13:07

プロセスのフォークや、受け渡しするデータのシリアライズ(pickle化)や、プロセス間の同期処理などの追加の作業が入るので少しは遅くなるでしょう。極端に違うなら別の原因(そもそも処理が違うとか)だと思います。 例えば、1万個ある要素にすべて同じ関数(ここでいうsubcalc)をmapを使って適用させる時、その関数は1万個の引数に対して合計で1万回呼び出されます。 それを、4プロセスで「分担」すると、1つのプロセスは2500回ぐらいを処理すれば済みます。 そうすると同期処理などで余計な処理が増えるので全体の作業量は*常に*増えます。 それでも「かかる時間」が短く済みます。 wordが1つの要素しかないならmapに渡してもsubcalcは1回しか呼び出されません。だから分担のしようがありません。
kohekoh

2017/07/26 13:25

すみません 何回も同じような質問になるのですが [['a','b','c'],['b','c','d'],['c','e']] これの要素は3つですよね もしmultiprocessingするなら、三回呼び出されるということでいいですよね?
kohekoh

2017/07/26 13:42

ちなみに少ないデータだと少しだけ早いのですが その4倍ほどのデータで行うと2倍ほど遅いです
quickquip

2017/07/26 14:00

いいですけど、そういう呼び方をしてIDFが計算されるようにはできてないですよね? (最初に話が戻りました)
quickquip

2017/07/26 14:01

nltkを使わないで計算できるようにsubcalcを書きかえたのならいいですけど。
kohekoh

2017/07/26 14:05

collection = nltk.TextCollection(word) words = [(i, collection) for i in word] doc = p.map(wrapper, words) #複数コアによる実行 このようにnltkの処理は外に出しています wrapper関数を別に作って、二つの引数をとってsabcalcを回しています
quickquip

2017/07/26 15:18

想像だと、collection が 文書の数分( len(words) 分)pickle化されるのに時間がかかる & メモリを圧迫するのかな? と思いました。 地道にメモリ使用量や時間がかかっている箇所を調べていくしかないでしょうね。
quickquip

2017/07/26 15:25 編集

すみません。pickleは関係ないかもしれません。pickle化できる必要があったような記憶があったのですが、ちょっと曖昧です
kohekoh

2017/07/27 01:47

ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問