コードの3行は、4倍のデータ処理速度を得るためにPythonスクリプトを作成します

PythonはPythonは、仕事のために非常に適している間、私たちは、このような再する必要があるとして、トレーニング機械学習モデルを使用する前にデータは、通常、データの前処理を必要としていたプログラミング言語を完了するために、データ処理や繰り返し作業の自動化のために非常に適しています十画像の何千ものの大きさ、Pythonの持つ問題なしを調整!あなたは、ほとんどの場合、簡単にデータ処理作業を完了することができますPythonライブラリを見つけることができます。

しかし、一方でPythonは、使いやすく習得が容易であるが、それは最速の言語ではありません。デフォルトでは、Pythonのは、1つのプロセスで実行されているCPUを使用しています。あなたが近年のコンピュータの構成である場合でも、通常はクアッドコアプロセッサ、つまり、4つのCPUがあります。これは、データ処理のためのPythonスクリプトを待っているとき、コンピュータが実際にそのことについて、アイドリング中のコンピューティングリソースの75%以上であることを意味します!

今日、我々は、Pythonの関数を並列に実行することにより、コンピュータのすべての処理能力を最大限に活用する方法を教えます。Pythonのconcurrent.futuresモジュールのおかげで、私たちは、通常のデータ処理シナリオスクリプトデータは、並行して4倍の速度を処理することができますになることができるようになり、3行のコードが必要になります。

通常のデータ処理方法のPython

Pythonの各画像のサムネイルを作成するために、我々は、画像データの完全なファイルフォルダを持っているとしましょう。

ここで、フォルダ内のすべてのJPEG画像ファイルのリストのための短いスクリプトは、Pythonのglob関数を内蔵し、その後128個のピクセルのサムネイルサイズとして各画像を保存するために枕画像処理ライブラリを使用します。

import glob
import os
from PIL import Image

def make_image_thumbnail(filename):
    # 缩略图会被命名为"<original_filename>_thumbnail.jpg"
    base_filename, file_extension = os.path.splitext(filename)
    thumbnail_filename = f"{base_filename}_thumbnail{file_extension}"

    # 创建和保存缩略图
    image = Image.open(filename)
    image.thumbnail(size=(128, 128))
    image.save(thumbnail_filename, "JPEG")

    return thumbnail_filename

# 循环文件夹中所有JPEG图像,为每张图像创建缩略图
for image_file in glob.glob("*.jpg"):
    thumbnail_file = make_image_thumbnail(image_file)

print(f"A thumbnail for {image_file} was saved as {thumbnail_file}")

スクリプトは、単純なパターンに従って、あなたは、多くの場合、データ処理スクリプトでこの方法が表示されます。

  • まず、あなたが処理したいファイル(またはその他のデータ)のリストを取得します
  • 上記1つのデータファイルを扱うことのできるヘルパー関数
  • 補助機能は、個々のデータの処理を一度に1つずつ、ループを必要とします。

私たちは、このスクリプトをテストするために、JPEG 1000画像クリップを含むファイルを使用して実行し、それにかかる時間を参照してください。

$ time python3 thumbnails_1.py
A thumbnail for 1430028941_4db9dedd10.jpg was saved as 1430028941_4db9dedd10_thumbnail.jpg
[... about 1000 more lines of output ...]
real 0m8.956s
user 0m7.086s
sys 0m0.743s

これは、プログラムを実行するために8.9秒かかりましたが、どのように実際の作業強度コンピュータを行いますか?

私たちは、その後のプログラムが実行された場合にアクティビティモニタのケースを見てもう一度プログラムを実行します。

![画像](http://upload-images.jianshu.io/upload_images/13090773-b965ee6f42944c06.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

コンピュータの処理リソースの75%はアイドル状態です!状況は何ですか?

この理由は、私のコンピュータは4 CPUを持っているということですが、唯一のPythonを使用しています。だから、プログラムは単に強度を勢揃いされ、CPUが、3さらに何もありません。私は、したがって、4つの別個の部分Iの並列処理に分割されて作業することが可能な方法が必要。幸いにも、Pythonは非常に簡単な方法は私たちが行うことができますがあります!

マルチプロセスを作成しよう

ここで私たちは、並列にデータを処理することを可能にする方法は次のとおりです。

1. JPEGファイルが4個に分割されます。

例2 4つの別々の実行Pythonインタプリタ。

Pythonの処置の3例にように、これらの4個のデータのそれぞれ。

4.これらの処理部4の結果は、最終結果のリストを取得するために合わせました。

パイソンの4つのコピーは、ワークロードは、右、についてですCPUよりも4倍高い処理することができる必要があり、4つの別々のCPU上で実行されますか?

すべてのベストは、Pythonは仕事の最も厄介な部分という私たちのために行っています。私達はちょうどそれがライン上で機能しているの使用のインスタンスを実行し、どのように多くしたいと伝える必要があり、それが残りの作業を完了します。私達はちょうど3行のコードの全過程を変更する必要があります。

まず第一に、我々はあなたがPythonで構築されたconcurrent.futuresライブラリをインポートする必要があります。

import concurrent.futures

次に、我々は、Pythonの起動に4つの追加Pythonの例を指示する必要があります。私たちは、Pythonのプロセスプールを作成することによって、次の操作を行います。

with concurrent.futures.ProcessPoolExecutor() as executor:

デフォルトでは、それはあなたのコンピュータ上の各CPU用のPythonプロセスを作成しますので、あなたは4 CPUを持っている場合、Pythonは4つのプロセスを開始します。

最後のステップは、プロセスプールは、データリストに私たちのヘルパー関数を実行するこれらの4つのプロセスで作成できるようにすることです。私たちはループのために持っている必要があり、これを実行します。

for image_file in glob.glob("*.jpg"):
thumbnail_file = make_image_thumbnail(image_file)

新しいコールexecutor.mapに置き換え():

image_files = glob.glob("*.jpg")for image_file, thumbnail_file in zip(image_files, executor.map(make_image_thumbnail, image_files)):

executor.map()関数呼び出しは、補助データ処理すべき機能のリストを入力します。この機能は、など、リストを含むすべての問題、の仕事は、複数のサブリストに分割され、サブリストは、それぞれの子プロセスに送信され、子プロセスが実行され、結果をマージされて完了するために、私を助けることができます よくやりました!

また、私たちのために、各関数呼び出しの結果を返すことができます。Executor.map()関数は、同程度の結果に応じて入力されたデータを返します。だから私は一歩は、元のファイル名と内のすべてのステップに一致し得るためのショートカットとしてPythonのジッパー()関数を使用していました。

ここでは、プログラムコードのこの変更後の3ステップは次のとおりです。

import glob
import os
from PIL import Image
import concurrent.futures

def make_image_thumbnail(filename):
    # 缩略图会被命名为 "<original_filename>_thumbnail.jpg"
    base_filename, file_extension = os.path.splitext(filename)
    thumbnail_filename = f"{base_filename}_thumbnail{file_extension}"

    # 创建和保存缩略图
    image = Image.open(filename)
    image.thumbnail(size=(128, 128))
    image.save(thumbnail_filename, "JPEG")

    return thumbnail_filename

# 创建Process Pool,默认为电脑的每个CPU创建一个
with concurrent.futures.ProcessPoolExecutor() as executor:
    # 获取需要处理的文件列表
    image_files = glob.glob("*.jpg")

    # 处理文件列表,但通过Process Pool划分工作,使用全部CPU!
    for image_file, thumbnail_file in zip(image_files, executor.map(make_image_thumbnail, image_files)):
        print(f"A thumbnail for {image_file} was saved as {thumbnail_file}")

私たちは、このスクリプトを実行し、データ処理を完了するために、より高速であるかどうかを確認します。

$ time python3 thumbnails_2.py
A thumbnail for 1430028941_4db9dedd10.jpg was saved as 1430028941_4db9dedd10_thumbnail.jpg
[... about 1000 more lines of output ...]
real 0m2.274s
user 0m8.959s
sys 0m0.951s

スクリプトは、データの取り扱いに2.2秒で終了しました!元のバージョンよりも4倍速いスピード!我々は1の代わりに4つのCPUを使用するので、より高速なデータを処理することができました。

あなたは慎重に見ている場合でも、あなたは、「ユーザー」の時間にはほぼ9秒を見つけるでしょう。なぜ2.2秒のプログラム処理時間が、私は方法を知っているか9秒の実行時間をしませんか?これは、ああそうにありませんか?

「ユーザー」CPU時間はすべての時間の合計があるためである、私たちは、仕事を仕上げる9秒ですが、我々は、4つの完全なCPUを使用すると、合計CPU時間、わずか2.2秒の実際のデータ処理時間!

注意:より多くのPythonのプロセスを有効にしてデータを配信することは子供に時間を要し、そのためこの方法に頼る常にスピードの大幅な増加を保証するものではありません。あなたは非常に大きなデータセットを扱うにしたい場合は、カットのセットへのデータの**どのように多くの作品を設定する記事がある紙は **、あなたが読むことができる、あなたはかなり役立ちます。

このメソッドは、いつも私はスクリプトが実行するデータ処理をスピードアップ?

あなたはデータの列があり、各データは、我々がここで話しているの良いアプローチを使用して、個別に処理することができればスピードのプロセスプールです。ここでは、並列処理を使用するためのいくつかの例は以下のとおりです。

  • 別のWebサーバログのシリーズからクロールの統計情報。
  • XML、CSVおよびJSONファイルの束からのデータを解析します。
  • 画像データの前処理の数が多い、機械学習データセットの確立。

しかし、我々はプロセスプールは万能薬ではない、覚えておいてください。使用プロセスのプールは、前後に別のPythonの処理プロセス間でデータを渡す必要があります。あなたが効果的にプロセスに転送することができないデータを処理したい場合は、このアプローチは動作しません。要するに、データはあなたのタイプに対処する方法を知っているのPythonを処理する必要があります。

一方、データは、期待シーケンスに従って処理することができません。あなたが次のステップの結果の前にさらに処理が必要な場合は、このアプローチは動作しません。

これGILの問題?

あなたは、Pythonのグローバルインタプリタロックという男(グローバルインタプリタロック)のもの、すなわち、GILを知っているかもしれません。これは、アプリケーションがマルチスレッドの場合でも、各スレッドが唯一のPythonコマンドを実行できることを意味します。GILは唯一のPythonのスレッドすべての回でそれを確認してください。言い換えれば、マルチスレッドのPythonコードは本当にマルチコアCPUをフルに活用することができない、並列に実行されません。

しかし、プロセスのプールは、この問題を解決することができます!私たちは別のPythonのインスタンスを実行しているので、各インスタンスは独自のGILを持っています。我々が得るようにPythonのコードは本当に並列処理であります!

並列処理を恐れてはいけません!

concurrent.futuresライブラリーでは、Pythonはあなたが単純にスクリプトを変更することができます、すぐに仕事に、コンピュータ上のすべてのCPUをしましょう。あなたはループのため、それは同じように簡単に習得した後、この方法を試すことを恐れてはいけないが、それは彼のダンスを来て、あなたのデータ処理スクリプトを作ることができます。

推奨読書:

チュートリアルの基礎知識ゼロPythonの最も詳細なソース

2019 Pythonの爬虫類の学習ロードマップのフルバージョン

なぜPythonはしっかりと最初のカードAI人工知能言語を確保することができます

Pythonの上昇、新しい高プログラミング言語のTIOBEリスト!

おすすめ

転載: blog.csdn.net/meiguanxi7878/article/details/93654980