はじめに
産業革命が社会を形作り、19 世紀のビクトリア時代の賑やかな生活様式が石畳の通りを形成した世界に足を踏み入れてください。ここでは、馬車の音が響き渡る霧がかかった路地裏や、遠くで工場の機械のうなり声が聞こえる中で、群がる人々を魅了する才能を持つ一人の人物が暮らしています。それは、同時に多くのことを行う信じられない能力で知られる通り芸人です。
私たちのパフォーマーであるオリバーは、ユニサイクルに乗ってバランスを保ちながら物をジャグリングし、ハーモニカを演奏し、同時に複雑な謎を解くことで知られています。オリバーのパフォーマンスは、聴衆を驚かせるほどシームレスで効率的であり、同時進行活動の達人である彼の腕前の証です。この実験では、Python のマルチスレッドとマルチプロセッシング機能を深く掘り下げることで、オリバーの多タスク処理の腕前を反映し、コーダーが問題なく同時に複数のタスクを管理できるようにします。
スレッドの理解
このステップでは、Python におけるスレッドの基本を学びます。スレッドを使うことで、複数の操作を同時に実行できるようになります。これにより、プログラムが一度に複数のことを行っているかのように見えるようになります。まるでオリバーが自転車に乗りながらジャグリングをする能力のようです。
~/project ディレクトリに次の内容の simple_threads.py という名前のファイルを開きます。
import threading
import time
def print_numbers():
for i in range(1, 6):
time.sleep(1)
print(i)
## Create two threads
thread1 = threading.Thread(target=print_numbers)
thread2 = threading.Thread(target=print_numbers)
## Start both threads
thread1.start()
thread2.start()
## Wait for both threads to complete
thread1.join()
thread2.join()
print("Done with numbers!")
ターミナルで次のコマンドで上記のコードを実行します。
python simple_threads.py
両方のスレッドから交互に数字が表示され、その後 "Done with numbers!" が表示されるはずです。
1
1
2
2
3
3
4
4
5
5
Done with numbers!
マルチプロセッシングの活用
次に、マルチプロセッシングを使って計算を高速化しましょう。Python のマルチプロセッシングは、複数のプロセスを実行できるようにします。これらのプロセスは異なる CPU コアで実行され、CPU バウンドなタスクに必要な全体の時間を短縮します。
~/project ディレクトリに次の内容の process_prime.py という名前のファイルを開きます。
from multiprocessing import Process
import math
def is_prime(num):
"""
数が素数かどうかを確認する。
"""
if num <= 1:
return False
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
return False
return True
def compute_primes(start, end):
"""
与えられた範囲内の素数を計算する。
"""
prime_numbers = [num for num in range(start, end) if is_prime(num)]
print(f"範囲 {start}-{end} 内の素数:{prime_numbers}")
processes = []
## 2 つのプロセスを作成
for i in range(0, 20000, 10000):
## compute_primes 関数をターゲットにし、範囲を引数として渡す新しいプロセスを作成
p = Process(target=compute_primes, args=(i, i+10000))
processes.append(p)
## プロセスを開始
p.start()
## すべてのプロセスが終了するまで待つ
for p in processes:
p.join()
print("素数計算が完了しました!")
ターミナルで次のコマンドでスクリプトを実行します。
python process_prime.py
これにより、指定された範囲内で見つかった素数が出力され、完了メッセージが表示されます。
範囲 0-10000 内の素数: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241,
......
9851, 9857, 9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929, 9931, 9941, 9949, 9967, 9973]
範囲 10000-20000 内の素数: [10007, 10009, 10037, 10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099, 10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163, 10169, 10177, 10181, 10193,
......
19739, 19751, 19753, 19759, 19763, 19777, 19793, 19801, 19813, 19819, 19841, 19843, 19853, 19861, 19867, 19889, 19891, 19913, 19919, 19927, 19937, 19949, 19961, 19963, 19973, 19979, 19991, 19993, 19997]
素数計算が完了しました!
まとめ
この実験では、ビクトリア時代の通り芸人の多層的なパフォーマンスに似たように、Python におけるスレッドとマルチプロセッシングのニュアンスを解き明かす魅力的な旅に出ました。まずはスレッドを使ってタスクをこなし、その後、CPU コア全体で大規模な操作を処理するように進化させました。この演習は、Python の並列処理能力を示すだけでなく、これらの技術が、オリバーというキャラクターの多面的な技術展示に似たように、現実世界でどのような意味を持つかを明らかにしました。
この実験からの学びとして、I/O バウンドなタスクに対する Python スレッドと、CPU バウンドなタスクに対するプロセスを明確に理解することが挙げられます。これにより、コーディングパフォーマンスが向上し、アプリケーションがより効率的になります。



