中学理科1630641 views
中学英語811710 views
世界の国564520 views
小学社会310485 views
中学社会668760 views
数学講師2886227 views
MathPython497343 views
高校国語788336 views
りんご209490 views
中学数学623755 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Python のマルチスレッドとマルチプロセスの使い分け

Python で並列処理を行う方法として、マルチスレッドとマルチプロセスがあります。それぞれに特徴があり、処理の内容によって使い分けが重要です。

基本的な違い

マルチスレッド

同じプロセス内でメモリを共有。GIL により同時に1スレッドだけが Python コードを実行。I/O バウンドな処理に適している。

マルチプロセス

独立したプロセスでメモリは分離。真の並列実行が可能。CPU バウンドな処理に適している。

GIL の影響

Python の GIL(Global Interpreter Lock)により、マルチスレッドでは CPU バウンドな処理の並列化ができません。

import threading
import multiprocessing
import time

def cpu_bound(n):
    """CPU を使う重い計算"""
    total = 0
    for i in range(n):
        total += i * i
    return total

N = 10_000_000

# シングルスレッド
start = time.time()
cpu_bound(N)
cpu_bound(N)
print(f"シングル: {time.time() - start:.2f}秒")

# マルチスレッド(GIL のため速くならない)
start = time.time()
t1 = threading.Thread(target=cpu_bound, args=(N,))
t2 = threading.Thread(target=cpu_bound, args=(N,))
t1.start(); t2.start()
t1.join(); t2.join()
print(f"マルチスレッド: {time.time() - start:.2f}秒")

# マルチプロセス(真の並列化)
start = time.time()
p1 = multiprocessing.Process(target=cpu_bound, args=(N,))
p2 = multiprocessing.Process(target=cpu_bound, args=(N,))
p1.start(); p2.start()
p1.join(); p2.join()
print(f"マルチプロセス: {time.time() - start:.2f}秒")

I/O バウンド処理にはスレッド

ファイル I/O やネットワーク通信など、待ち時間が多い処理にはスレッドが適しています。

from concurrent.futures import ThreadPoolExecutor
import urllib.request
import time

def download(url):
    response = urllib.request.urlopen(url)
    return len(response.read())

urls = ["https://example.com"] * 5

start = time.time()
with ThreadPoolExecutor(max_workers=5) as executor:
    results = list(executor.map(download, urls))
print(f"スレッド: {time.time() - start:.2f}秒")

I/O 待ち中は GIL が解放されるため、スレッドが効果的です。

CPU バウンド処理にはプロセス

数値計算や画像処理など、CPU を使う処理にはプロセスが適しています。

from concurrent.futures import ProcessPoolExecutor
import time

def compute(n):
    return sum(i * i for i in range(n))

numbers = [5_000_000] * 4

start = time.time()
with ProcessPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(compute, numbers))
print(f"プロセス: {time.time() - start:.2f}秒")
print(f"結果: {results}")

使い分けの判断基準

処理の種類推奨理由
ファイル読み書きスレッドI/O 待ち中に他のスレッドが動ける
ネットワーク通信スレッドI/O 待ちが多い
数値計算プロセスCPU を使うので真の並列化が必要
画像処理プロセスCPU バウンド
データ変換プロセスCPU バウンド

メモリ共有の違い

import threading
import multiprocessing

shared_list = []

def append_thread(item):
    shared_list.append(item)  # 同じリストを共有

def append_process(item):
    shared_list.append(item)  # 別プロセスなので反映されない

# スレッド
t = threading.Thread(target=append_thread, args=("thread",))
t.start(); t.join()
print(f"スレッド後: {shared_list}")  # ['thread']

# プロセス
p = multiprocessing.Process(target=append_process, args=("process",))
p.start(); p.join()
print(f"プロセス後: {shared_list}")  # ['thread'](変わらない)

プロセス間でデータを共有するには、QueueManager を使う必要があります。

作成コストの違い

スレッド

作成コストが低い。メモリ効率が良い。大量に作成しても問題ない。

プロセス

作成コストが高い。メモリを多く消費。作成数を抑えるべき。

組み合わせて使う

I/O と CPU の両方がある場合は、組み合わせることもあります。

from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
import urllib.request

def download(url):
    response = urllib.request.urlopen(url)
    return response.read()

def process_data(data):
    # CPU を使う処理
    return len(data) * 2

# ダウンロード(I/O)はスレッドで
with ThreadPoolExecutor(max_workers=5) as executor:
    downloaded = list(executor.map(download, ["https://example.com"] * 5))

# データ処理(CPU)はプロセスで
with ProcessPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(process_data, downloaded))

まとめ

スレッドを選ぶ場合

I/O バウンドな処理。軽量な並行処理。データ共有が多い場合。

プロセスを選ぶ場合

CPU バウンドな処理。真の並列化が必要。メモリ分離が必要。

処理の特性を理解して、適切な並列化手法を選びましょう。