pythonはどのように並列しますか
pythonはどのように並列しますか
マルチスレッドデータのセキュリティを保証するため、python言語の設計では、グローバル解釈ロックGIL(global interpretor lock)があり、各スレッドは実行開始時にロックを取得しなければならず、I/Oやsleepが掛けられたときにロックを解放し、同じ時刻に1つのスレッドだけが実行されることを保証し、複数のスレッドは異なるタイムスライス上で実行され、マルチタスクの目的を達成する.pythonに同時機能を持たせ、pythonがCPUの単一コアを十分に使用できるようにします.マルチスレッドはpythonネットワーク爬虫類で同時に使用されるのが一般的で、大量のダウンロードタスクを一度に開くことができ、ほとんどのタスクはI/Oの状態を待っており、単一スレッドよりも数倍速く、また、コパスを使用してもマルチスレッドの効果を達成することができます.多くの場合、効率を向上させ、マルチコアCPUの優位性を十分に利用し、同時に複数のタスクを実行し、マルチタスクを並列に行うには、どうすればいいのでしょうか.GILを迂回できない以上、解決策は次のとおりです.マルチプロセスを使用し、複数のpythonインスタンスを開き、プロセスプールを使用する C/C++でマルチスレッドコードを書き出し、cythonで呼び出す.あるいはC/C++をdllファイル(linuxではsoファイル)にコンパイルし、 インタプリタは、C言語版のPyhtonではなく、jpython(java)、python(python)、ironpython(C#)などを使用 note:python 2の単一スレッドは、固定バイトコードを実行するたびにGILロックをアクティブに解放し、python 3では固定時間毎にGILロックをアクティブに解放するように変更されます.
pythonマルチスレッドdemo
マルチコアCPU上で上記コードを実行すると,スレッド数が1であろうと10であろうと,実行時間はほぼ同じであり,マルチスレッドはマルチコアの利点を利用して効率を向上させることはできない.
pythonマルチプロセスdemo
マルチコアCPUで実行すると、2つのプロセスは1つよりも明らかに速く、効率の差は明らかですが、マルチプロセスのシステムオーバーヘッドも大きくなります.note:windows上で実行する場合、マルチプロセスコードは必ず
cythonマルチスレッドdemo
マルチプロセスシステムのオーバーヘッドが大きく、pythonという動的言語の実行効率が高くない.すなわち、マルチプロセスを使用するとパフォーマンスのボトルネックに直面する可能性がある.この場合、C/C++言語の優位性を利用して、キー部分を書き換え、pythonから呼び出し、C/C++を通じてGILの制約を受けないマルチスレッドを直接使用し、コード性能を高めることができる.テストのために、C言語で簡単なデッドサイクルを書いて、1つのコアしか利用できないことを発見して、CPUを最大化するために、またマルチスレッドを必要として、マルチスレッドを作成するにはオペレーティングシステムが提供するカーネルの方法を利用しなければならなくて、linuxとwindowsの実現の上で違いがあります.
linuxマルチスレッドdemo
gccでコンパイルすればいいのに、8スレッドで降りると、家庭用CPUが100%近くになります
Windowsマルチスレッドdemo
Visual Studioが持参したMSVCコンパイルで実行し、同様にCPUも100%近い
cythonのシンプルな使い方
cythonは言語であり、文法はC言語とpythonの混合体であり、単独では実行できない.コードファイルの接尾辞は
(2). コンパイル用
(3). 実行
(4). pythonインタプリタを開いて実行
上記windowsの下のマルチスレッドコードをどのように利用してcpuを十分に使用するかは、同様に4つのステップである:(1).cythonファイル(
(2). コンパイル用
(3). 実行
(4). pythonインタプリタを開いて実行
マルチスレッドデータのセキュリティを保証するため、python言語の設計では、グローバル解釈ロックGIL(global interpretor lock)があり、各スレッドは実行開始時にロックを取得しなければならず、I/Oやsleepが掛けられたときにロックを解放し、同じ時刻に1つのスレッドだけが実行されることを保証し、複数のスレッドは異なるタイムスライス上で実行され、マルチタスクの目的を達成する.pythonに同時機能を持たせ、pythonがCPUの単一コアを十分に使用できるようにします.マルチスレッドはpythonネットワーク爬虫類で同時に使用されるのが一般的で、大量のダウンロードタスクを一度に開くことができ、ほとんどのタスクはI/Oの状態を待っており、単一スレッドよりも数倍速く、また、コパスを使用してもマルチスレッドの効果を達成することができます.多くの場合、効率を向上させ、マルチコアCPUの優位性を十分に利用し、同時に複数のタスクを実行し、マルチタスクを並列に行うには、どうすればいいのでしょうか.GILを迂回できない以上、解決策は次のとおりです.
ctypes
モジュールを介して直接コードを呼び出す.pythonのCインタフェースで拡張を書くか、Boost.を使います.Pythonなど.pythonマルチスレッドdemo
import time
from threading import Thread
def countdown(n):
while n > 0:
n -= 1
count = 2e7
start = time.time()
n_threads = 10 #
threads = [Thread(target=countdown, args=(count//n_threads,)) for i in range(n_threads)]
for t in threads: t.start() #
for t in threads: t.join() #
print(time.time() - start)
マルチコアCPU上で上記コードを実行すると,スレッド数が1であろうと10であろうと,実行時間はほぼ同じであり,マルチスレッドはマルチコアの利点を利用して効率を向上させることはできない.
pythonマルチプロセスdemo
import time
import os
from multiprocessing import Pool
def countdown(n):
while n > 0:
n -= 1
if __name__ == "__main__":
count = 2e7
start = time.time()
# n_processes = os.cpu_count()
n_processes = 8 #
pool = Pool(processes=n_processes) #
for i in range(n_processes):
pool.apply_async(countdown, (count//n_processes,)) #
pool.close() #
pool.join() #
print(time.time() - start)
マルチコアCPUで実行すると、2つのプロセスは1つよりも明らかに速く、効率の差は明らかですが、マルチプロセスのシステムオーバーヘッドも大きくなります.note:windows上で実行する場合、マルチプロセスコードは必ず
if __name__ == '__main__':
の中で実行しなければならない.そうしないと、これらのグローバル式はサブプロセスでも実行され、クラッシュするまで多くのプロセスが生成され続け、linuxでfork呼び出しでマルチプロセスを実現するのとは全く異なる.cythonマルチスレッドdemo
マルチプロセスシステムのオーバーヘッドが大きく、pythonという動的言語の実行効率が高くない.すなわち、マルチプロセスを使用するとパフォーマンスのボトルネックに直面する可能性がある.この場合、C/C++言語の優位性を利用して、キー部分を書き換え、pythonから呼び出し、C/C++を通じてGILの制約を受けないマルチスレッドを直接使用し、コード性能を高めることができる.テストのために、C言語で簡単なデッドサイクルを書いて、1つのコアしか利用できないことを発見して、CPUを最大化するために、またマルチスレッドを必要として、マルチスレッドを作成するにはオペレーティングシステムが提供するカーネルの方法を利用しなければならなくて、linuxとwindowsの実現の上で違いがあります.
linuxマルチスレッドdemo
// mthread_linux.c
#include
#include
int thread_run(int thread_id)
{
int s = 0;
printf("thread %i started...
", thread_id);
for (size_t i = 0; i < 4000000000; i++)
for (size_t j = 0; j < 5; j++)
s += j;
printf("%i: %d
", thread_id, s);
int ret = thread_id;
return ret;
}
int main()
{
const size_t num_threads = 8;
// pthread_t threads[num_threads];
pthread_t threads[8];
for (size_t i = 0; i < num_threads; i++)
{
int t_id = i+1;
pthread_create(threads + i, NULL, (void *)&thread_run, (void *)t_id);
printf("thread %lu created
", i + 1);
}
for (size_t i = 0; i < num_threads; i++)
{
void *ret_val;
int exit_code = pthread_join(threads[i], &ret_val);
printf("thread %lu exited with %d and returned %d.
", i + 1, exit_code, (int)ret_val);
}
return 0;
}
// &&
// gcc mthreads_linux.c -lpthread && ./a.out
gccでコンパイルすればいいのに、8スレッドで降りると、家庭用CPUが100%近くになります
Windowsマルチスレッドdemo
// mthread_windows.cpp
#include
#include
DWORD WINAPI thread_run(LPVOID lp_thread_id)
{
int thread_id = *(int*)lp_thread_id;
int s = 0;
printf("thread %i started...
", thread_id);
for (size_t i = 0; i < 4000000000; i++)
for (size_t j = 0; j < 5; j++)
s += j;
printf("%i: %d
", thread_id, s);
int ret = thread_id;
return ret;
}
int main()
{
const size_t num_threads = 8;
// HANDLE threads[num_threads];
HANDLE threads[8];
for (size_t i = 0; i < num_threads; i++)
{
int t_id = i + 1;
threads[i] = CreateThread(NULL, 0, thread_run, &t_id, 0, NULL);
printf("thread %lu created
", i + 1);
}
for (size_t i = 0; i < num_threads; i++)
{
int exit_code = WaitForSingleObject(threads[i], INFINITE);
printf("thread %lu exited with %d.
", i + 1, exit_code);
}
getchar();
return 0;
}
Visual Studioが持参したMSVCコンパイルで実行し、同様にCPUも100%近い
cythonのシンプルな使い方
cythonは言語であり、文法はC言語とpythonの混合体であり、単独では実行できない.コードファイルの接尾辞は
.pyx
.pyx
ファイルに翻訳する必要がある.c
ファイルをC言語コンパイラで生成し、接尾辞は.so
(linux)または.pyd
(windows)であり、python解釈器で直接import呼び出しが可能である.略語コードの文法によって、Cモードで実行するかPythonモードで実行するか、完全にCモードで実行すると極めて効率的であり、cythonの公式ドキュメントによると、cythonを使用する最も簡単な例は4ステップである:(1).cythonファイルの作成(hello.pyx
)def say_hello_to(name):
print("Hello %s!" % name)
(2). コンパイル用
hello.pyx
のファイルを作成する(setup.py
)from distutils.core import setup
from Cython.Build import cythonize
setup(
name="hello module",
ext_modules=cythonize("hello.pyx")
)
(3). 実行
python setup.py build_ext --inplace
、このステップ生成hello.cp36-win_amd64.pyd
ファイル(windows,python 36,64 bit)は、この列を気にせずコンパイル要求パソコンにVisual Studio(Windows)またはgcc(linux)をインストール(4). pythonインタプリタを開いて実行
from hello import say_hello_to
cythonはC言語で書かれたコードを呼び出します上記windowsの下のマルチスレッドコードをどのように利用してcpuを十分に使用するかは、同様に4つのステップである:(1).cythonファイル(
demo.pyx
)を作成し、参照mthread_windows.cpp
の関数をpython関数_main
内に包むcdef extern from "mthread_windows.cpp":
int main()
def _main():
main()
(2). コンパイル用
demo.pyx
のファイルを作成する(setup.py
)from distutils.core import setup
from Cython.Build import cythonize
setup(
name="demo module",
ext_modules=cythonize("demo.pyx")
)
(3). 実行
python setup.py build_ext --inplace
、このステップ生成demo.cp36-win_amd64.pyd
ファイル(windows,python 36,64 bit)(4). pythonインタプリタを開いて実行
from demo import _main