1. บทนำ

ความสำคัญของการประมวลผลแบบขนานใน Python

Python เป็นภาษาการเขียนโปรแกรมที่เรียบง่ายและใช้งานง่าย จึงถูกนำไปใช้ในหลากหลายด้าน อย่างไรก็ตาม เมื่อมีการประมวลผลข้อมูลหรือการคำนวณที่ซับซ้อน ความเร็วของ Python อาจกลายเป็นข้อจำกัด เพื่อแก้ไขปัญหานี้ การใช้ “การประมวลผลแบบขนาน” ซึ่งสามารถทำงานหลายงานพร้อมกันได้ จึงมีบทบาทสำคัญ บทความนี้จะอธิบายวิธีการนำการประมวลผลแบบขนานมาใช้ใน Python ตั้งแต่แนวทางพื้นฐานไปจนถึงตัวอย่างการใช้งานจริง

2. วิธีการประมวลผลแบบขนานใน Python

วิธีหลักของการประมวลผลแบบขนาน

Python มีหลายวิธีในการทำงานแบบขนาน โดยหลัก ๆ มี 3 วิธีดังนี้:

  1. มัลติเธรด (threading โมดูล)
    ใช้หลายเธรดเพื่อทำงานพร้อมกัน แต่ด้วยข้อจำกัดของ GIL (Global Interpreter Lock) ใน Python ทำให้ประสิทธิภาพถูกจำกัดในงานที่ใช้ CPU หนัก
  2. มัลติโปรเซส (multiprocessing โมดูล)
    แต่ละโปรเซสมีหน่วยความจำแยกกัน ทำให้ไม่ถูกจำกัดด้วย GIL และสามารถใช้ CPU หลายคอร์ได้เต็มที่ เหมาะกับการประมวลผลข้อมูลขนาดใหญ่และงานคำนวณหนัก
  3. การประมวลผลแบบอะซิงโครนัส (asyncio โมดูล)
    เหมาะสำหรับงานที่เป็น I/O-bound (เช่น การสื่อสารเครือข่ายหรือการอ่าน/เขียนไฟล์) ช่วยให้สามารถจัดการเวลารอคอยได้อย่างมีประสิทธิภาพ
侍エンジニア塾

3. มัลติโปรเซส vs มัลติเธรด

ผลกระทบของ GIL (Global Interpreter Lock)

Python มีระบบที่เรียกว่า GIL ทำให้ในเวลาเดียวกันมีเพียงเธรดเดียวที่ทำงานได้ สิ่งนี้เป็นสาเหตุที่การประมวลผลแบบเธรดไม่สามารถเพิ่มประสิทธิภาพในงานที่ใช้ CPU มากได้ จึงเหมาะกับงาน I/O-bound ที่มีเวลารอคอยมากกว่า

ข้อดีและข้อจำกัดของมัลติเธรด

เธรดมีความเบา และเหมาะสำหรับงาน I/O เช่น การอ่านไฟล์หรือการเชื่อมต่อเครือข่าย แต่ไม่เหมาะสำหรับงานที่ใช้ CPU หนัก เนื่องจาก GIL ทำให้ไม่สามารถใช้ CPU หลายคอร์ได้เต็มที่

“`python
import threading
import time

def worker(num):
print(f”Worker {num} starting”)
time.sleep(2)
print(f”Worker {num} finished”)

threads = [] for i in range(5):
t = threading.Thread(target=worker, args=(i,))
threads.append(t)
t.start()

for t in threads:
t.join()
“`

โค้ดนี้แสดงการทำงานของ 5 เธรดพร้อมกัน โดยแต่ละเธรดจะหน่วงเวลา 2 วินาทีแล้วจบการทำงาน การใช้มัลติเธรดช่วยให้เห็นการทำงานพร้อมกันได้ชัดเจน

ข้อดีของมัลติโปรเซส

มัลติโปรเซสสามารถหลีกเลี่ยงข้อจำกัดของ GIL ได้ แต่ละโปรเซสทำงานในหน่วยความจำแยกกัน ทำให้สามารถใช้ CPU หลายคอร์ได้เต็มประสิทธิภาพ โดยเฉพาะอย่างยิ่งในงานที่คำนวณหนักหรือต้องจัดการข้อมูลขนาดใหญ่

“`python
from multiprocessing import Process
import time

def worker(num):
print(f”Worker {num} starting”)
time.sleep(2)
print(f”Worker {num} finished”)

if __name__ == ‘__main__’:
processes = [] for i in range(5):
p = Process(target=worker, args=(i,))
processes.append(p)
p.start()

for p in processes:
p.join()
“`

ตัวอย่างนี้แสดงการทำงานของ 5 โปรเซสพร้อมกัน แต่ละโปรเซสทำงานแยกจากกัน และ `join()` จะรอให้ทุกโปรเซสทำงานเสร็จสิ้นก่อนโปรแกรมจะไปต่อ

4. วิธีการนำการประมวลผลแบบขนานไปใช้ใน Python

การใช้โมดูล multiprocessing

โมดูล multiprocessing สามารถจัดการหลายโปรเซสได้อย่างมีประสิทธิภาพ ตัวอย่างโค้ดด้านล่างเป็นการใช้ process pool ในการคำนวณ

“`python
from multiprocessing import Pool

def square(x):
return x * x

if __name__ == ‘__main__’:
with Pool(4) as p:
result = p.map(square, [1, 2, 3, 4, 5])
print(result)
“`

โค้ดนี้ใช้ 4 โปรเซสในการคำนวณกำลังสองของตัวเลขในลิสต์ ผลลัพธ์ที่ได้จะเป็นลิสต์ที่มีค่าคำนวณเสร็จ

年収訴求

5. การประมวลผลแบบอะซิงโครนัสและการใช้งาน

การใช้ asyncio

asyncio เหมาะสำหรับงานที่มีการรอ I/O เช่น การสื่อสารเครือข่ายหรือไฟล์ I/O โดยระหว่างรอสามารถทำงานอื่น ๆ ไปพร้อมกันได้

“`python
import asyncio

async def worker(num):
print(f’Worker {num} starting’)
await asyncio.sleep(1)
print(f’Worker {num} finished’)

async def main():
tasks = [worker(i) for i in range(5)] await asyncio.gather(*tasks)

asyncio.run(main())
“`

โค้ดนี้รัน 5 งานแบบอะซิงโครนัสพร้อมกัน ใช้ `await` เพื่อรอในแต่ละงานโดยไม่บล็อกงานอื่น

6. การปรับจูนประสิทธิภาพของการประมวลผลแบบขนาน

การใช้ Joblib

Joblib เป็นไลบรารีที่ช่วยให้การประมวลผลข้อมูลหรือการฝึกโมเดล Machine Learning มีประสิทธิภาพมากขึ้น ตัวอย่างเช่น:

“`python
from joblib import Parallel, delayed

def heavy_task(n):
return n ** 2

results = Parallel(n_jobs=4)(delayed(heavy_task)(i) for i in range(10))
print(results)
“`

โดยกำหนด n_jobs เพื่อควบคุมจำนวนโปรเซสที่ทำงานพร้อมกัน

7. การประยุกต์ใช้งานจริงของการประมวลผลแบบขนานใน Python

การประมวลผลข้อมูลและการ Web Scraping

การใช้การประมวลผลแบบขนานใน Python มีประโยชน์อย่างมาก เช่น ในการดึงข้อมูลจากหลายเว็บไซต์พร้อมกัน (web scraping) หรือการประมวลผลข้อมูลจำนวนมาก รวมถึงการฝึกโมเดล Machine Learning ด้วย multiprocessing หรือ Joblib

8. สรุป

การประมวลผลแบบขนานเป็นเทคนิคสำคัญที่จะช่วยให้ Python ทำงานได้เต็มประสิทธิภาพ การใช้ threading, multiprocessing, asyncio, และ Joblib อย่างเหมาะสม จะช่วยเพิ่มประสิทธิภาพในงานหลากหลายประเภทได้อย่างมาก