พื้นฐาน multiprocessing
ใช้แกน CPU หลายแกน
พื้นฐาน multiprocessing เป็นบทเรียน Python Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Python Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน
เหตุใดจึงใช้การประมวลผลหลายกระบวนการ
GIL ป้องกันไม่ให้เธรดทำงานไบต์โค้ด Python แบบขนานกัน โมดูล multiprocessing แก้ข้อจำกัดนี้ด้วยการเปิดใช้ กระบวนการแยกกัน โดยแต่ละกระบวนการมีตัวแปลภาษาและ GIL ของตนเอง ดังนั้นงานที่ใช้ CPU เป็นหลักจึงทำงานบนหลายแกนประมวลผลได้อย่างแท้จริง
import multiprocessing as mp
print('CPU cores available:', mp.cpu_count())การเริ่มต้นกระบวนการ
Process(target=func) มีรูปแบบการใช้งานคล้ายกับส่วนติดต่อสำหรับเธรด ให้เรียก start() เพื่อเริ่มทำงาน และเรียก join() เพื่อรอ
import multiprocessing as mp
def worker():
print('hello from a child process')
if __name__ == '__main__':
p = mp.Process(target=worker)
p.start()
p.join()
print('parent done')ตัวป้องกันการทำงานหลัก
ในบางแพลตฟอร์ม กระบวนการลูกจะนำเข้าสคริปต์ของคุณ หากไม่มีตัวป้องกัน if __name__ == '__main__': คุณอาจสร้างกระบวนการซ้ำไปเรื่อย ๆ ได้ ให้ครอบโค้ดที่ใช้เริ่มการทำงานไว้ภายในตัวป้องกันนี้เสมอ
import multiprocessing as mp
def task(n):
print('processing', n)
if __name__ == '__main__':
for i in range(3):
p = mp.Process(target=task, args=(i,))
p.start()
p.join()การส่งอาร์กิวเมนต์
ใช้ args สำหรับอาร์กิวเมนต์ตามตำแหน่ง และใช้ kwargs สำหรับอาร์กิวเมนต์แบบคีย์เวิร์ด เช่นเดียวกับเธรด อาร์กิวเมนต์จะถูกแปลงเป็นข้อมูลสำหรับส่ง และส่งไปยังกระบวนการลูก
import multiprocessing as mp
def show(label, times):
for _ in range(times):
print(label)
if __name__ == '__main__':
p = mp.Process(target=show, args=('hi',), kwargs={'times': 2})
p.start()
p.join()กลุ่มกระบวนการทำงาน
multiprocessing.Pool จัดการกลุ่มกระบวนการ pool.map แบ่งอ็อบเจ็กต์ที่วนซ้ำได้ให้กระบวนการเหล่านั้น และรวบรวมผลลัพธ์ตามลำดับ
import multiprocessing as mp
def square(n):
return n * n
if __name__ == '__main__':
with mp.Pool(processes=2) as pool:
print(pool.map(square, range(6)))ProcessPoolExecutor
ส่วนติดต่อ concurrent.futures ยังมี ProcessPoolExecutor ซึ่งใช้ส่วนติดต่อ submit/map แบบเดียวกับที่คุณเห็นในเธรด
from concurrent.futures import ProcessPoolExecutor
def cube(n):
return n ** 3
if __name__ == '__main__':
with ProcessPoolExecutor() as ex:
print(list(ex.map(cube, range(5))))พื้นที่หน่วยความจำแยกกัน
แต่ละกระบวนการมีหน่วยความจำของตนเอง การแก้ไขตัวแปรโกลบอลในกระบวนการลูกจะไม่เปลี่ยนสำเนาของกระบวนการแม่ ข้อมูลต้องถูกส่งคืนหรือแบ่งปันอย่างชัดเจน
import multiprocessing as mp
counter = 0
def bump():
global counter
counter += 100
if __name__ == '__main__':
p = mp.Process(target=bump)
p.start()
p.join()
print('parent counter still:', counter)การรับผลลัพธ์กลับมา
เนื่องจากไม่มีการใช้หน่วยความจำร่วมกัน ให้ส่งผลลัพธ์กลับผ่าน Pool.map ตัวดำเนินการ หรือคิว แทนการแก้ไขตัวแปรโกลบอล
import multiprocessing as mp
def double(n):
return n * 2
if __name__ == '__main__':
with mp.Pool(2) as pool:
results = pool.map(double, [1, 2, 3, 4])
print('results:', results)apply_async สำหรับการเรียกใช้ครั้งเดียว
apply_async จัดกำหนดการเรียกใช้หนึ่งครั้งและส่งคืนตัวจัดการผลลัพธ์ ให้เรียก .get() เพื่อดึงค่ากลับมา
import multiprocessing as mp
def add(a, b):
return a + b
if __name__ == '__main__':
with mp.Pool(2) as pool:
r = pool.apply_async(add, (3, 4))
print(r.get())ข้อกำหนดการแปลงข้อมูล
เป้าหมายและอาร์กิวเมนต์ต้องสามารถแปลงเป็นข้อมูลสำหรับส่งได้ เพื่อให้ข้ามขอบเขตระหว่างกระบวนการได้ ฟังก์ชันระดับบนสุดใช้งานได้ แต่ฟังก์ชันแลมบ์ดาและฟังก์ชันภายในมักใช้งานไม่ได้
import multiprocessing as mp
def top_level(n):
return n + 1
if __name__ == '__main__':
with mp.Pool(2) as pool:
print(pool.map(top_level, [10, 20]))เมื่อใดควรเลือกใช้กระบวนการ
ใช้กระบวนการกับงานที่ใช้ CPU เป็นหลัก เช่น การคำนวณทางคณิตศาสตร์ การประมวลผลภาพ และการแยกวิเคราะห์ ค่าใช้จ่ายในการสร้างกระบวนการและแปลงข้อมูลทำให้เหมาะกับงานจำนวนน้อยที่มีขนาดใหญ่กว่า มากกว่างานเล็ก ๆ จำนวนมาก
import multiprocessing as mp
def heavy(n):
return sum(i * i for i in range(n))
if __name__ == '__main__':
with mp.Pool() as pool:
print(pool.map(heavy, [1000, 2000, 3000]))ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจของคุณเกี่ยวกับการประมวลผลหลายกระบวนการ
ทบทวน
คุณได้เรียนรู้พื้นฐานการประมวลผลหลายกระบวนการ:
- กระบวนการหลีกเลี่ยง GIL ได้ จึงทำงานบน CPU แบบขนานได้จริง
- ใช้ตัวป้องกัน
if __name__ == '__main__' PoolและProcessPoolExecutorกระจายงานและรวบรวมผลลัพธ์- ไม่มีการใช้หน่วยความจำร่วมกัน อาร์กิวเมนต์จึงต้องสามารถแปลงเป็นข้อมูลสำหรับส่งได้
ถัดไป: การแบ่งปันข้อมูลอย่างปลอดภัยด้วยคิวและล็อก
คำถามที่พบบ่อย
บทเรียน “พื้นฐาน multiprocessing” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “พื้นฐาน multiprocessing” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Python Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Python Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “พื้นฐาน multiprocessing”
ใช้แกน CPU หลายแกน คุณปฏิบัติ Python Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Python Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Python Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “พื้นฐาน multiprocessing” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Python Academy นี้ได้ไหม
ได้ บทเรียน Python Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- เธรดและ GIL
- ThreadPoolExecutor
- พื้นฐาน multiprocessing
- การแบ่งปันข้อมูลอย่างปลอดภัย