มีเครื่องมือหรือวิธีการใดบ้างที่สามารถเพิ่มความเร็วให้กับโค้ดที่เขียนใน Python


29

แบ็คกราวน์:ฉันคิดว่าฉันอาจต้องการพอร์ตโค้ดบางอย่างที่คำนวณเมทริกซ์เอ็กซ์โปเนนเชียล - เวกเตอร์ผลิตภัณฑ์โดยใช้วิธีการย่อย Krylov จาก MATLAB ถึง Python (โดยเฉพาะฟังก์ชั่นexpmvpของJitse Niesenซึ่งใช้อัลกอริทึมที่อธิบายไว้ในบทความนี้) อย่างไรก็ตามฉันรู้ว่าถ้าฉันใช้ฟังก์ชั่นจำนวนมากจากโมดูลที่ได้มาจากไลบรารีที่รวบรวม (เช่นฉันใช้ raw Python เท่านั้น ในฟังก์ชั่น) แล้วมันอาจจะค่อนข้างช้า

คำถาม:มีเครื่องมือหรือวิธีการใดบ้างที่สามารถช่วยฉันเร่งความเร็วโค้ดที่ฉันเขียนใน Python เพื่อประสิทธิภาพการทำงาน โดยเฉพาะอย่างยิ่งฉันสนใจเครื่องมือที่ทำให้กระบวนการเป็นไปโดยอัตโนมัติมากที่สุดแม้ว่าวิธีการทั่วไปจะได้รับการต้อนรับเช่นกัน

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


ฉันให้คำตอบแบบ Python- sepcificกับคำถามนี้: scicomp.stackexchange.com/questions/2429/ …ฉันคิดว่าคำแนะนำและลิงก์ที่มีจะเป็นประโยชน์สำหรับคุณ
AlexE

(h / t ถึง @AlexE ที่ทำให้ฉันตระหนักถึงสิ่งนี้) มีการทับซ้อนกันระหว่างคำถามนี้อย่างแน่นอน(วิธี) เขียนแบบจำลองที่ทำงานได้เร็วขึ้น? และอะไรคือกลยุทธ์ที่ดีสำหรับการปรับปรุงประสิทธิภาพของรหัสของฉัน . การผสานบางอย่างอาจเป็นไปตามลำดับ ฉันโพสต์เกี่ยวกับเรื่องนี้ใน Meta
Geoff Oxberry

1
นอกจากคำตอบที่ดีที่นี่ลองดูที่ลิงค์นี้
Mike Dunlavey

คำตอบ:


40

ฉันจะแบ่งคำตอบออกเป็นสามส่วน การทำโปรไฟล์เร่งโค้ดไพ ธ อนด้วย c และเร่งไพ ธ อนผ่านไพ ธ อน ฉันคิดว่า Python มีเครื่องมือที่ดีที่สุดในการดูประสิทธิภาพของรหัสของคุณจากนั้นเจาะลงไปที่คอขวดจริง การเร่งโค้ดโดยไม่มีการทำโปรไฟล์นั้นเหมือนกับการพยายามฆ่ากวางด้วย uzi

หากคุณกำลังสนใจจริงๆเท่านั้นในผลิตภัณฑ์เสื่อ vec ฉันอยากจะแนะนำscipy.sparse

เครื่องมือ Python สำหรับการทำโปรไฟล์

โมดูลโปรไฟล์และ cProfile :โมดูลเหล่านี้จะให้การวิเคราะห์เวลาทำงานมาตรฐานและสแตกการเรียกฟังก์ชันของคุณ มันค่อนข้างดีที่จะบันทึกสถิติและใช้โมดูล pstats คุณสามารถดูข้อมูลได้หลายวิธี

kernprof : เครื่องมือนี้รวบรวมกิจวัตรหลายอย่างไว้ด้วยกันเพื่อทำสิ่งต่าง ๆ เช่นการจับเวลาด้วยรหัสบรรทัด

memory_profiler : เครื่องมือนี้สร้างการพิมพ์ตามหน่วยความจำบรรทัดของโค้ดของคุณ

ตัวจับเวลา IPython :timeitฟังก์ชั่นค่อนข้างดีสำหรับการเห็นความแตกต่างของฟังก์ชั่นในวิธีการโต้ตอบที่รวดเร็ว

เร่งความเร็ว Python

Cython : cython เป็นวิธีที่รวดเร็วที่สุดในการใช้ฟังก์ชั่นบางอย่างใน python และรับโค้ดที่เร็วขึ้น คุณสามารถตกแต่งฟังก์ชั่นด้วยตัวแปรของไพ ธ อนของไพ ธ อนและสร้างรหัส c นี่คือการบำรุงรักษามากและยังสามารถเชื่อมโยงไปยังรหัสที่เขียนด้วยมืออื่น ๆ ใน c / c ++ / fortran ค่อนข้างง่าย มันเป็นเครื่องมือที่ต้องการในปัจจุบัน

ctypes : ctypes จะช่วยให้คุณสามารถเขียนฟังก์ชั่นของคุณใน c แล้วห่อมันอย่างรวดเร็วด้วยการตกแต่งที่เรียบง่ายของรหัส มันจัดการกับความเจ็บปวดทั้งหมดของการคัดเลือกนักแสดงจาก PyObjects และจัดการ gil เพื่อเรียกใช้ฟังก์ชัน c

มีวิธีการอื่นสำหรับการเขียนโค้ดของคุณใน C แต่ทั้งหมดนั้นค่อนข้างมากกว่าสำหรับการใช้ไลบรารี่ C / C ++ และห่อมันไว้ใน Python

วิธีการเฉพาะ Python

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

numpy : อาเรย์ที่แน่นอนสำหรับการดำเนินการของอาเรย์อย่างรวดเร็ว

numexpr : เครื่องมือเพิ่มประสิทธิภาพนิพจน์อาเรย์ numpy จะช่วยให้การแสดงออกหลายแถวอาร์เรย์ numpy และยังได้รับการกำจัดชั่วคราวจำนวนมากทำให้เนื่องจากการ จำกัด ของล่ามหลาม

blist : การนำ b-tree ไปใช้ของรายการรวดเร็วมากสำหรับการแทรกการทำดัชนีและการย้ายโหนดภายในของรายการ

แพนด้า : เฟรมข้อมูล (หรือตาราง) การวิเคราะห์ที่รวดเร็วมากในอาร์เรย์

pytables : ตารางที่มีโครงสร้างแบบรวดเร็ว (เช่น hdf5) ซึ่งเหมาะอย่างยิ่งสำหรับการคำนวณหลักและแบบสอบถามสำหรับข้อมูลขนาดใหญ่


3
คุณสามารถใช้ ctypes เพื่อเรียกรูทีน Fortran ได้เช่นกัน
Matthew Emmett


ถ้าพูดถึงการห่อรหัส f2py จะเป็นอย่างไร?
astrojuanlu

f2py เป็นเครื่องมือที่ยอดเยี่ยมและถูกใช้โดยหลาย ๆ คนในชุมชน fwrap เป็นสิ่งทดแทนล่าสุดเมื่อ f2py แสดงอายุของมัน แต่มันไม่สมบูรณ์
aterrel

ขอบคุณ! เหล่านี้เป็นประเภทของทรัพยากรที่ฉันกำลังมองหา ฉันรู้แค่บางคนเท่านั้นและเมื่อผ่านไป (หรือจากการดูบนอินเทอร์เน็ต) แอรอนพูดถึง numexpr มันทำงานอย่างไร มันจะนำไปใช้?
Geoff Oxberry

7

ก่อนอื่นถ้ามีการใช้งาน C หรือ Fortran (ฟังก์ชั่น MATLAB MEX?) ทำไมคุณไม่เขียน wrapper Python?

หากคุณต้องการใช้งานของคุณเองไม่เพียง แต่ wrapper ฉันขอแนะนำให้ใช้โมดูล numpy สำหรับพีชคณิตเชิงเส้น ตรวจสอบให้แน่ใจว่าเชื่อมโยงกับ Blas ที่ได้รับการปรับปรุงแล้ว (เช่น ATLAS, GOTOblas, uBLAS, Intel MKL, ... ) และใช้ Cython หรือสาน อ่านบทความPython ของ Performanceนี้เพื่อการแนะนำที่ดีและเป็นมาตรฐาน การใช้งานที่แตกต่างกันในบทความนี้สามารถดาวน์โหลดได้ที่นี่โดยได้รับความอนุเคราะห์จาก Travis Oliphant (Numpy-guru)

โชคดี.


บทความ Performance Python นั้นดูค่อนข้างเก่า แต่ไม่ได้กล่าวถึงเครื่องมือใหม่ที่มีให้เช่น numexpr
Aron Ahmadia

ฉันมองข้าม NUM ไปอย่างแน่นอน มันจะดีถ้าได้ใช้มาตรฐาน laplace เดียวกันกับ numexpr ...
GertVdE

คือscipy.weaveยังคงใช้และการพัฒนา? ดูเหมือนว่าบทความ Performance Python จะแสดงให้เห็นว่าสามารถใช้งานได้เร็วและให้การปรับปรุงความเร็วค่อนข้างดี แต่ฉันไม่ค่อยเห็นว่ามีการกล่าวถึงนอกบทความนั้น
Ken

@ เคน: scipy.weave เป็นเท่าที่ฉันรู้ไม่ได้อยู่ภายใต้การพัฒนาที่ใช้งานอยู่ มันถูกเก็บไว้สำหรับความเข้ากันได้ย้อนหลัง แต่มีการสนับสนุนให้มีโครงการใหม่ที่ใช้ Cython
GertVdE

สำหรับ GotoBLAS และ NumPy / SciPy ให้ดูder-schnorz.de/2012/06/optimized-linear-algebra-and-numpyscipy
AlexE

4

โดยทั่วไปฉันเห็นด้วยกับคำตอบอื่น ๆ ตัวเลือกที่ดีที่สุดสำหรับpythonรหัสตัวเลขที่รวดเร็วคือ

  • ใช้ไลบราพิเศษเช่น numpy
  • ตัดโค้ดที่มีอยู่ของคุณเพื่อให้pythonโปรแกรมของคุณสามารถโทรหาได้โดยตรง

แต่ถ้าคุณต้องการที่จะเขียนโปรแกรมขั้นตอนวิธีการทั้งจากรอยขีดข่วน (ผมพูดว่า "ผมเพียง แต่ใช้งูหลามดิบ") แล้วคุณอาจต้องการที่จะต้องพิจารณาhttp://pypy.org/ JIT (Just In Time) pythonการดำเนินงานของ ฉันไม่สามารถใช้มันสำหรับโครงการของฉันได้ (เพราะนั่นเป็นสิ่งที่ต้องอาศัยnumpyและpypyพวกเขากำลังทำงานอย่างหนักเพื่อสนับสนุนสิ่งนั้น) แต่มาตรฐานนั้นค่อนข้างน่าประทับใจ ( http://speed.pypy.org/ )


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.