# ประสิทธิภาพของ Python: ลูป NumPy แบบเนทีฟ, Callbacks และค่าใช้จ่ายในการแปลง

Published: 2026-10-17

การทดสอบตัวเลขที่ควบคุมด้วย CPU เท่านั้น ติดตามค่าที่เหมือนกันผ่านลูป CPython, การคำนวณ NumPy, Wrapper Callback ของ Python และลูป Numba ที่คอมไพล์แล้ว NumPy ที่มีอินพุตพร้อมใช้งานมีผลนำอย่างมาก ในขณะที่การแปลงจากและกลับไปเป็นรายการ Python ลดข้อดีนั้นให้เกือบเท่ากัน ตอนนี้อธิบายถึงขอบเขตการดำเนินการและวิธีวัดผลลัพธ์ที่แอปพลิเคชันต้องการ

Canonical: https://thedailydiff.dev/th/video/2026-10-17-python-native-loops/

## วิดีโอนี้ครอบคลุมอะไรบ้าง

- CPython คอมไพล์ซอร์สโค้ดเป็น bytecode การทำงานของ interpreter/object ซ้ำๆ และลูปตัวเลขเนทีฟที่มีประเภทเป็นการจัดเรียงการดำเนินการที่แตกต่างกัน
- การคำนวณเชิงตัวเลขของ NumPy สามารถส่งชุดข้อมูลที่มีประเภทไปยังการดำเนินการที่คอมไพล์แล้วได้ ลูปการคำนวณยังคงมีอยู่ และมุมมองสามารถมีโครงสร้างที่ไม่ต่อเนื่องกันได้
- วัดการแปลงและการแสดงผลลัพธ์ที่ต้องการ ในการรันนี้ การแปลงรายการ Python เป็นอาร์เรย์และย้อนกลับลบข้อได้เปรียบของอาร์เรย์ที่พร้อมใช้งานจำนวนมาก
- ภาระงานขนาดเล็กอาจชอบ Python ทั่วไปเนื่องจากค่าใช้จ่ายคงที่ในการเรียกอาร์เรย์มีความสำคัญ การทำความเข้าใจแปดค่าชนะการเปรียบเทียบที่วัดได้นี้
- np.vectorize เป็น Wrapper ที่สะดวกสบายที่เรียก Python สำหรับองค์ประกอบที่ต่อเนื่องกัน อินเทอร์เฟซแบบแบทช์เพียงอย่างเดียวไม่สามารถสร้างการดำเนินการตัวเลขแบบเนทีฟได้
- ลูปไวยากรณ์ Python ที่คอมไพล์แล้วก็สามารถเร็วได้เช่นกัน รวมถึงค่าใช้จ่ายในการคอมไพล์/ตั้งค่าเมื่อเริ่มต้นเมื่อมีความสำคัญต่อผู้เรียก
- การดำเนินการแบบเนทีฟ, CPU SIMD, Multithreading และแบ็คเอนด์ GPU เป็นแนวคิดที่แยกจากกัน คุณสมบัติ CPU ที่มีอยู่ไม่ได้ติดตามคำสั่งที่ใช้ในการรันที่เฉพาะเจาะจง

## บท

- 0:00 ทำไม CPU ตัวเดียวกันถึงเสร็จเร็วขึ้นได้?
- 0:52 ลูป Python ทำงานซ้ำอะไรบ้าง?
- 1:38 NumPy ย้ายลูปไปที่ไหน?
- 2:13 เร็วหมายถึง GPU หรือหลายคอร์ CPU หรือไม่?
- 2:49 ความเร็วที่น่าประทับใจจะหายไปเมื่อใด?
- 3:28 ขอบเขตใดที่ควรอยู่ในเกณฑ์มาตรฐาน?
- 4:00 ลูป Python ที่คอมไพล์แล้วก็เร็วได้ด้วยหรือไม่?
- 4:56 np.vectorize ทำงานอะไรจริงๆ?
- 5:41 คุณควรเปลี่ยนอะไรในโค้ดของคุณ?

## บทถอดเสียงที่แปลแล้ว

แปลจากการบรรยายภาษาอังกฤษต้นฉบับ เสียงและคำบรรยายที่มีให้จะควบคุมโดย YouTube

### ทำไม CPU ตัวเดียวกันถึงเสร็จเร็วขึ้นได้?

0:00 คุณคิดว่า Python ต้องการภาษาใหม่เพื่อให้เร็วขึ้น CPU ตัวเดียวกันรันชุดข้อมูลของเราเร็วขึ้นหลังจากที่ย้ายลูป งานหายไปไหน? ความเร็วจะหายไปเมื่อใด? ทางลัดใดที่นำ Python กลับมา? นี่คือ The Daily Diff, ภายใต้ฝากระโปรง จับตาดูทางลัดนั้นไว้ CPython คือการใช้งาน Python มาตรฐาน

0:17 มันคอมไพล์ซอร์สโค้ดของคุณเป็น bytecode จากนั้นรันคำสั่งเหล่านั้นใน interpreter NumPy เป็นไลบรารีตัวเลขที่อาร์เรย์เก็บค่าที่มี ประเภทข้อมูลที่ประกาศไว้ การคำนวณที่สร้างขึ้นสามารถส่งชุดข้อมูลทั้งหมดไปยังการดำเนินการที่คอมไพล์แล้วได้ ลองใช้ค่าจุดทศนิยมหนึ่งล้านค่า ยกกำลังสองแต่ละค่า จากนั้นเพิ่มค่าเริ่มต้น ทุกเวอร์ชันได้รับค่าที่เหมือนกันและให้คำตอบที่ตรงกัน ค่ามีขนาดเล็กพอที่จะป้องกันความแตกต่างของการปัดเศษออกจากการแข่งขัน

0:40 บนเครื่องนี้ การทำความเข้าใจใช้เวลาประมาณสามสิบสามมิลลิวินาที NumPy ใช้เวลาน้อยกว่าหนึ่งมิลลิวินาที ทั้งสองทำงานบน CPU นั่นเป็นหลักฐานที่เป็นประโยชน์สำหรับภาระงานนี้ และเป็นข่าวร้ายสำหรับ ภาษาโปรแกรม เริ่มต้นด้วยลูปปกติ

### ลูป Python ทำงานซ้ำอะไรบ้าง?

0:53 Python ได้รับค่าถัดไป ทำการคำนวณ และเพิ่มคำตอบ จากนั้นก็ทำซ้ำอีกครั้ง การคูณมีราคาถูก การจัดเตรียมการคูณครั้งถัดไป และการจัดการกับวัตถุ Python รอบๆ เพิ่มงานทุกครั้ง นี่คือการแยกส่วนของฟังก์ชันที่ทดสอบจริง การวนซ้ำ การคูณ และการบวกปรากฏเป็นคำสั่ง bytecode เวอร์ชันและ interpreter ของ Python เลือกแตกต่างกัน

1:14 ช่วงเวลาเหล่านี้เป็นของเวอร์ชันที่แสดงบนหน้าจอ ซึ่งก็คือ Python 3.10 รายการ Python เก็บการอ้างอิงถึงวัตถุ ดังนั้นสิ่งของประเภทต่างๆ จึงสามารถ ใช้รายการร่วมกันได้ งานคำนวณของเราใช้ตัวเลขตลอด มันจ่ายสำหรับการจัดเตรียมทั่วไปในขณะที่ร้องขอบริการที่ซ้ำซาก ลองนึกภาพการสั่งกาแฟแก้วเดียวกันเป็นล้านครั้งและกรอกแบบฟอร์มใหม่ สำหรับทุกแก้ว เครื่องชงกาแฟก็ใช้ได้

1:36 งานเอกสารกลับมีอาชีพเป็นของตัวเอง

### NumPy ย้ายลูปไปที่ไหน?

1:38 NumPy เปลี่ยนสัญญา อาร์เรย์นี้เก็บค่าจุดทศนิยมขนาดคงที่ที่มีประเภทที่ประกาศไว้เพียงประเภทเดียว อาร์เรย์ของเราเป็นแบบต่อเนื่อง ดังนั้นค่าต่างๆ จึงอยู่รวมกันในหน่วยความจำ มุมมองสามารถมีโครงสร้างอื่นได้ การดำเนินการคำนวณรู้ว่ากำลังรับข้อมูลประเภทใด การเรียกจะส่งชุดข้อมูลไปยังการดำเนินการแบบเนทีฟ ลูปยังคงเข้าถึงค่าภายในโค้ดที่คอมไพล์แล้ว มันสามารถใช้ความรู้เกี่ยวกับประเภทซ้ำๆ ในการทำงานนั้นได้

2:00 Python ยังคงเป็นผู้ส่งมอบงาน Itamar Turner Trauring อธิบายความแตกต่างใน Python Speed อินเทอร์เฟซแบบแบทช์ การนำไปใช้งานแบบเนทีฟ และคำสั่งเวกเตอร์ของโปรเซสเซอร์เป็น สิ่งต่างๆ ที่แยกจากกัน ชื่อฟังก์ชันให้หลักฐานน้อยมาก

### เร็วหมายถึง GPU หรือหลายคอร์ CPU หรือไม่?

2:13 ผลลัพธ์นี้ใช้ NumPy บน CPU แบ็คเอนด์ GPU เช่น CuPy เลือกตำแหน่งอื่นสำหรับอาร์เรย์และการดำเนินการ การซื้อ GPU ทำให้ลูป Python ทั่วไปนี้ยังคงทำงานในที่ที่มันทำงานอยู่แล้ว คำสั่งเวกเตอร์ของ CPU สามารถประมวลผลหลายค่าพร้อมกันได้ NumPy มีกลไกในการเลือกเคอร์เนลที่รองรับ รันไทม์ของเรารายงานคุณสมบัติที่มีอยู่ แต่ไม่ได้ติดตามคำสั่งของนิพจน์นี้ การให้ gain ที่วัดได้ทั้งหมดแก่คำสั่งเวกเตอร์จะเป็นการ โฆษณาเกินจริง

2:40 ตะกร้าสินค้า GPU ยังคงปิดอยู่ มีบางอย่างที่น่าพึงพอใจอย่างยิ่งเกี่ยวกับการแก้ไขประสิทธิภาพที่ยังยกเลิกการ ซื้อได้ด้วย น่าเสียดายที่เกณฑ์มาตรฐานยังคงดำเนินต่อไป

### ความเร็วที่น่าประทับใจจะหายไปเมื่อใด?

2:49 ด้วยแปดค่า การทำความเข้าใจชนะ การเรียกกลไกอาร์เรย์มีค่าใช้จ่ายมากกว่างานเล็กๆ อาร์เรย์พร้อมใช้งานที่ใหญ่ขึ้นดึงขึ้นนำ เราใช้การทดลองซ้ำและกระบวนการที่อุ่นเครื่องแล้ว บิลด์ Python รุ่นใหม่สามารถเปลี่ยนจุดตัดได้ จากนั้นเปลี่ยนสิ่งที่แอปพลิเคชันต้องการ เริ่มต้นด้วยรายการ Python และจบด้วยรายการ Python ใหม่ NumPy ต้องแปลงอินพุตเป็นอาร์เรย์และเปลี่ยนคำตอบกลับเป็นวัตถุ Python

3:11 ขั้นตอนเหล่านั้นเป็นส่วนหนึ่งของค่าใช้จ่ายหากแอปพลิเคชันของคุณต้องการ ที่ค่าหนึ่งล้านค่า เส้นทางที่สมบูรณ์นั้นใช้เวลาประมาณยี่สิบแปดมิลลิวินาที การทำความเข้าใจก็ใช้เวลาประมาณยี่สิบแปดมิลลิวินาทีเช่นกัน การนำที่น่าทึ่งของเรากลายเป็นการเสมอเกือบเท่ากัน ส่วนที่เร็วเป็นเรื่องจริง ข้อได้เปรียบขึ้นอยู่กับการปล่อยให้ข้อมูลอยู่ในรูปแบบตัวเลข

### ขอบเขตใดที่ควรอยู่ในเกณฑ์มาตรฐาน?

3:28 ติดตามข้อมูล หากการดำเนินการถัดไปรับอาร์เรย์ ให้เก็บอาร์เรย์ไว้ หากคุณแปลงระหว่างรายการและอาร์เรย์ซ้ำๆ ให้วัดการข้ามเหล่านั้น การหยุดก่อนการส่งมอบที่มีค่าใช้จ่ายสูงจะให้ตัวเลขที่ถูกต้องสำหรับคำถามที่ผิด การคูณอาร์เรย์นี้สร้างผลลัพธ์ชั่วคราว การเพิ่มค่าเริ่มต้นสร้างเอาต์พุต การดำเนินการแบบเนทีฟยังคงต้องการหน่วยความจำและย้ายข้อมูล

3:47 การดำเนินการบางอย่างยอมรับบัฟเฟอร์เอาต์พุต ซึ่งช่วยลดการจัดสรรเมื่อโค้ดของคุณสามารถ นำกลับมาใช้ใหม่ได้อย่างปลอดภัย หนึ่งบรรทัดที่สวยงามสามารถสั่งบัฟเฟอร์ขนาดใหญ่หลายตัวได้ Python Speed ก็ชี้ให้เห็นปัญหานี้เช่นกัน allocator ไม่สนใจสุนทรียภาพของคุณอย่างน่าประหลาดใจ

### ลูป Python ที่คอมไพล์แล้วก็เร็วได้ด้วยหรือไม่?

4:00 คุณยังสามารถรักษารูปแบบลูปและเปลี่ยนการดำเนินการได้ Numba สามารถคอมไพล์ฟังก์ชัน Python เชิงตัวเลขที่รองรับเป็นโค้ดเนทีฟได้ นี่คือลูปจากการทดสอบของเราพร้อมด้วย decorator ของคอมไพเลอร์ มันยังคงเขียนว่า for เส้นทาง interpreter ที่มีค่าใช้จ่ายสูงได้เปลี่ยนไปแล้ว หลังจากคอมไพล์ ลูปนี้ใช้เวลาน้อยกว่าครึ่งมิลลิวินาทีกับอาร์เรย์ที่พร้อมใช้งาน การคอมไพล์เองใช้เวลาประมาณหนึ่งวินาทีในการรันนี้ ค่าใช้จ่ายในการตั้งค่านั้นถูกยกเว้นจากการจับเวลาซ้ำๆ

4:22 ดังนั้นงานเล็กๆ น้อยๆ เพียงครั้งเดียวจึงควรได้รับการเปรียบเทียบที่แตกต่างกัน คู่มือของ Numba เองก็ยินดีที่จะแสดงลูปที่ชัดเจน การเริ่มต้นการโยกย้ายภาษาโดยไม่พบ hot path เป็นวิธีที่ซับซ้อนในการ หลีกเลี่ยงการเปิด profiler ขั้นแรกให้หาสิ่งที่ใช้เวลา การรอเครือข่าย การแยกวิเคราะห์วัตถุ และการคำนวณจำนวนมากต้องการการแก้ไขที่แตกต่างกัน การดำเนินการอาร์เรย์แบบเนทีฟช่วยได้เมื่อการคำนวณและข้อมูลเข้ากันได้

4:43 วัดผลลัพธ์ที่ผู้เรียกของคุณต้องการจริงๆ ตอนนี้สำหรับทางลัดนั้น คุณมีฟังก์ชัน Python และต้องการให้มันยอมรับอาร์เรย์ Wrapper ที่ชื่อ vectorize ดูเหมือนปุ่มประสิทธิภาพที่ขาดหายไป เอกสารประกอบมีประโยคสำคัญรออยู่

### np.vectorize ทำงานอะไรจริงๆ?

4:56 NumPy กล่าวว่า wrapper vectorize ของมันมีไว้เพื่อความสะดวกเป็นหลัก การนำไปใช้งานเป็นหลักคือลูป for Wrapper ยอมรับชุดข้อมูล แต่ยังคงเรียกฟังก์ชัน Python ของคุณสำหรับ องค์ประกอบที่ต่อเนื่องกัน อินเทอร์เฟซสั้นลง ขอบเขตการดำเนินการยังคงยุ่งอยู่ ดูค่าเดียวกันกลับมาผ่าน callback ของ Python ด้วยอาร์เรย์ที่พร้อมใช้งาน เวอร์ชันนี้ใช้เวลาประมาณแปดสิบเจ็ดมิลลิวินาที มันช้ากว่าการทำความเข้าใจของเรา

5:18 Wrapper การกระจายที่ใช้งานได้สามารถรักษางานแต่ละองค์ประกอบที่คุณพยายามจะ ลบออกได้ ตรวจสอบการนำไปใช้งานเบื้องหลังอินเทอร์เฟซแบบแบทช์ เก็บข้อมูลที่เข้ากันได้ในรูปแบบที่เป็นประโยชน์ และรวมการแปลงในการเปรียบเทียบ และรวมการแปลงในการเปรียบเทียบ ลูปแบบเนทีฟ, callback และคอมไพล์สามารถดูคล้ายกันจากมุมมองของผู้เรียก ชื่อ vectorize ให้คำมั่นสัญญาที่นาฬิกาจับเวลาของคุณไม่เคยเซ็นรับรอง เก็บไว้เมื่อความสะดวกสบายคือสิ่งที่คุณต้องการ สำหรับประสิทธิภาพ ให้ตรวจสอบลูปที่ทำงาน

### คุณควรเปลี่ยนอะไรในโค้ดของคุณ?

5:41 คำตัดสินของฉันคือ SHIP IT สำหรับการจัดกลุ่ม hot path เชิงตัวเลขที่วัดได้ เก็บลูปปกติไว้เมื่อมันทำงานได้ดีอยู่แล้ว ตรวจสอบว่างานเกิดขึ้นที่ไหนและผู้เรียกคนถัดไปต้องการอะไร สมัครสมาชิก กดกระดิ่ง และบอกฉันในความคิดเห็นว่าคุณจะประทับตรามัน แตกต่างกันหรือไม่ และนั่นคือความแตกต่างสำหรับวันนี้ ฉันชื่อ Niko จาก Axrisi รวมอย่างมีความรับผิดชอบ

## แหล่งที่มา

- [Universal functions (ufunc) basics — NumPy 2.2](https://numpy.org/doc/2.2/user/basics.ufuncs.html) — NumPy
- [The N-dimensional array — NumPy 2.2](https://numpy.org/doc/2.2/reference/arrays.ndarray.html) — NumPy
- [numpy.vectorize — convenience and performance notes](https://numpy.org/doc/2.2/reference/generated/numpy.vectorize.html) — NumPy
- [CPU/SIMD optimizations — NumPy 2.2](https://numpy.org/doc/2.2/reference/simd/index.html) — NumPy
- [dis — Disassembler for Python bytecode](https://docs.python.org/3.10/library/dis.html) — Python Software Foundation
- [CPython 3.10.12 list representation](https://github.com/python/cpython/blob/v3.10.12/Include/cpython/listobject.h) — CPython contributors
- [The limits of Python vectorization as a performance technique](https://pythonspeed.com/articles/vectorization-python-alternatives/) — Itamar Turner-Trauring / Python⇒Speed
- [Performance Tips](https://numba.readthedocs.io/en/stable/user/performance-tips.html) — Numba
- [Basics of CuPy](https://docs.cupy.dev/en/stable/user_guide/basic.html) — CuPy
