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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python

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

Q&A

4回答

984閲覧

python の並列化により、行変換処理の速度を上げたい

kazuya_

総合スコア82

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python

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

1グッド

2クリップ

投稿2022/10/13 00:27

環境
windows10、 Vscode、 python 2.88

pythonで、下記のようにCSVファイルから行単位のデータを取り込んで
各行を並列に処理し、速度を上げたいと考えました。
threadとprocessでmapにより並列化しましたが、普通にloop処理した方が
10倍近く早く、逆に大幅に遅くなりました。
速度を上げたいのですが、どのような方法があるでしょうか?

python

1import time 2from concurrent.futures import ThreadPoolExecutor 3# from concurrent.futures import ProcessPoolExecutor 4 5def list_app(row): 6 d_row = row.split(',') 7 row = row + ',' + d_row[5] + ',' + d_row[6] + ',' + d_row[7] 8 return row 9 10if __name__=='__main__': 11 12 d_f_con=[] 13 thread_flag = True 14 15 with open('C:/Users/fxscX0cd6/Documents/test.csv','r',encoding='shift-jis') as f: 16 f_con=f.readlines() 17 18 startt = time.time() 19 20 if thread_flag == False: 21 for i,row in enumerate(f_con): 22 d_row = row.split(',') 23 row = row + ',' + d_row[5] + ',' + d_row[6] + ',' + d_row[7] 24 d_f_con.append(row) 25 26 else: 27 with ThreadPoolExecutor(max_workers=10) as executor: 28 # with ProcessPoolExecutor(max_workers=10) as executor: 29 results = executor.map(list_app, f_con) 30 results = list(results) 31 32 endt=time.time() -startt 33 34 print(endt)

threadとprocess仕様で1秒くらい、通常loopで0.1秒くらいでした。

melianを押しています

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

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

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

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

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

bsdfan

2022/10/13 02:16

速度を上げたい理由はなんでしょう? ・ファイルが大量にある ・実際のファイルのサイズはもっと大きい ・実際はもっと複雑な処理をしていて時間がかかっている それによって、とれる方法が違ってくると思います。
jbpb0

2022/10/13 04:16 編集

> threadとprocess仕様で1秒くらい マルチスレッドよりもマルチプロセスの方が、もっと遅くなりませんか? (プロセスの生成の方が、スレッドの生成よりも時間がかかるため) google colabで、 xxx = np.random.rand(100000, 10) np.savetxt('test.csv', xxx, delimiter=',') で作ったcsvファイルを使って質問のコードを実行したら、実行時間は下記の通りでした 並列化無し:0.2秒くらい マルチスレッド:3秒くらい マルチプロセス:30秒くらい
quickquip

2022/10/13 04:45 編集

Pythonのバージョンはなにかの書き間違いですか? (それとも本当にPython2系を使っている? VS Codeのプラグインのバージョンを書いてしまったとかもありえる?) 追加: concurrent がある以上2系なはずはなかったですね
guest

回答4

0

pandas を使用してみてはいかがでしょうか。
for文より高速に処理できます。
以下のようなコードで、list_app関数に近い処理ができると思います。

Python

1import pandas as pd 2 3df = pd.read_csv(file_path) 4 5df_list_app = df[['col_5', 'col_6', 'col_7']]

投稿2022/10/13 03:16

fpfpfp

総合スコア55

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

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

kazuya_

2022/10/13 04:12

ご回答ありがとうございます。 実際には、splitでなくて正規表現を作成する処理なのですが、 たぶん1行に数秒かかっている可能性があります。 pandasは確か、C++で作成されているんですかね。 split等使用時には、参考にさせていただきます。
kazuya_

2022/10/14 01:44

ご連絡ありがとうございました。 参考にさせていただきます。 文字列を正規表現に置き換える処理を行っています。
guest

0

並列処理をする場合には、プロセスやスレッドの準備や生成・削除など、並列処理をするために追加で必要な処理の時間(オーバーヘッド)がかかります。処理の内容や分割方法などによってはそのオーバーヘッドほ方が大きくなってしまう場合があります。

今回の例では、処理内容そのものが時間がかからないものなので、並列化の恩恵が受けられないということでしょう。

投稿2022/10/13 00:54

編集2022/10/13 02:44
TakaiY

総合スコア14369

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

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

kazuya_

2022/10/13 02:25

ご回答ありがとうございます。 わかりにくい質問で申し訳ありません。 オーバーヘッドについては、それが原因だと気づいております。 ただ、メモリ上に展開していますので、ここまで差があると使い物にならないような気がします。 コーディングの工夫(thread系の別のライブラリの使用)で、もう少し何とかならないものでしょうか?
TakaiY

2022/10/13 02:44

ならないでしょう。 使いものにならないということはまったくありません。 たとえば、1行の処理に10分かかるような処理を1000行分やる場合、直列であれば10000分(2.8時間)かかるところを並列でやれば10分の1とか100分の1の時間で済みます、オーバーヘッドは30秒かかりますが影響は無視できます、というのが並列処理です。 充分な恩恵です。
kazuya_

2022/10/13 04:14

そうですね。オーバーヘッドの時間がずっと一定だとして、1行で数秒の処理ですと 恩恵があるかもしれません。少し試してからまた、投稿いたします。
kazuya_

2022/10/13 06:13

1行3秒の処理で44行をLOOPしてみました。 結果、threadを使用しない場合128秒に対して、max_workersを10から5とかに変化させましたが、 約125から127秒となり、ほぼ差がありませんでした。 このことから、concurrent.futuresの使用では恩恵がほぼ無いようです。 processのほうは、正規表現の関数を使用したためか、エラーになったのでやっていません。
TakaiY

2022/10/13 06:46

情報ありがとうございます。 その 1行3秒の処理というのはどういった処理でしょう。pythonにはGIL(global interpreter lock)という制約がありまして、処理内容によってはマルチスレッドで高速化しにくいのです。
kazuya_

2022/10/14 01:28

なるほど re.searchで検索した結果を、ディクショナリ配列に格納していく処理を処理時間延長の為 10000回LOOPしています。 どうやら、排他ロックを繰り返しながら、1行づつ実行している状態のようです。 ファイルの読み込み等のI/O関係か、あるいはGILのないライブラリを使用する方法に限定されてしまいますね
TakaiY

2022/10/14 02:51

そうですね。 もしくは、マルチプロセスにするか。
guest

0

GILを無効化したpythonで実行したら1/2程度まで速くなりました。
https://github.com/colesbury/nogil

投稿2022/10/17 13:36

a.com

総合スコア916

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

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

0

以下、実行環境です。

bash

1$ lsb_release -d 2Description: Ubuntu 22.04.1 LTS 3 4$ uname -isr 5Linux 5.15.0-22-generic x86_64 6 7$ cat /proc/cpuinfo | grep model.name | head -1 8model name : Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz 9 10# CPU 数 11$ nproc 126 13 14# CSV ファイルの行数(1億行) 15$ wc -l test.csv 16100000000 test.csv

質問に掲載されているコードで thread_flag = False とした場合の実行時間は、55.18664 sec になりました。

以下のコードでは ProcessPoolExecutor() を使っていて、CSV ファイルを 192 分割、6 個のプロセスで並列処理しています。実行時間は 18.27044 sec でした。
result の中身はリストのリストになっています

python

1import os 2import concurrent.futures as cf 3from time import time 4 5def list_app(cbegin, cend): 6 global f_con 7 splitted = [] 8 for r in f_con[cbegin:cend]: 9 row = r.rstrip() 10 d_row = row.split(',') 11 row += ',' + d_row[5] + ',' + d_row[6] + ',' + d_row[7] 12 splitted.append(row) 13 14 return splitted 15 16def app(lines, workers, nchunks): 17 chunksize = lines // nchunks 18 with cf.ProcessPoolExecutor(max_workers=workers) as executor: 19 cbegin = [chunksize * i for i in range(nchunks)] 20 cend = cbegin[1:] + [lines] 21 result = executor.map(list_app, cbegin, cend) 22 23 return result 24 25if __name__ == '__main__': 26 with open('test.csv', 'r') as f: 27 f_con = f.readlines() 28 29 lines = len(f_con) 30 workers = os.cpu_count() 31 nchunks = workers * 32 32 33 start = time() 34 result = app(lines, workers, nchunks) 35 result = list(result) 36 duration = time() - start 37 38 print(f'{duration:.5f} sec')

投稿2022/10/13 16:52

melian

総合スコア21190

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問