Performance Measurement and Improvement Techniques
จาก Morange Wiki
เนื้อหา
เทคนิคการเพิ่มประสิทธิภาพและปรับปรุงให้ดียิ่งขึ้น
วัตถุประสงค์
- ในการประมวลผลภาพ คุณจะเจอกับกระบวนทางทางคณิตสาตร์หรือทางด้านอื่นๆเยอะมาก ดังนั้น โค๊ดที่คุณ
เขียนยังไม่ได้รับการปรับปรุงแก้ไขให้อยู่ในลักษณะที่รวดเร็วขึ้น
สิ่งที่จะเรียนรู้
- วัดคุณภาพหรือประสิทธิภาพของ Code ที่พัฒนา
- นำเทคนิคมาปรับปรุงให้ Code ดีขึ้น
- เรียนรู้การใช้ functions : cv2.getTickCount และ cv2.getTickFrequency
- นอกเหนือจาก OpenCV และ Python แล้ว ยังมี Module ที่ช่วยในการวัดระยะเวลาของการดำเนินงาน โดยจะ ออกรายงานเกี่ยวกับรายละเอียดของโค๊ดที่พัฒนา เช่น ว่าเราใช้เวลาเท่าไหร่ในการ Run ฟังก์ชั่น สัก 1 ฟังก์ชั่น
หากต้องการที่จะใช้งาน มีโปรแกรมชื่อว่า IPython ที่มีฟังก์ชั่นเข้ามาช่วยเหลือในด้านนี้ และยังมีลักษณะการใช้งานที่ง่ายอีกด้วย
วัดประสิทธิภาพด้วย OpenCV
- cv2.getTickCount เป็นฟังก์ชั่นที่จะ Return จำนวนของ clock-cycles หลังจากรายการที่เกี่ยวข้องกันถูกเรียกใช้งาน และหากว่าคุณเรียกใช้ฟังก์ชั่นนี้ ก่อนและหลังที่รันโปรแกรม คุณจะได้รับจำนวนของ clock-cycles ที่ใช้ไปในการรันฟังก์ชั่น
- cv2.getTickFrequency ฟังก์ชั่นนี้จะ returns ค่าความถี่ของ clock-cycles หรือ จำนวน clock-cycles ต่อวินาทีเพื่อหาจำนวนวินาทีที่รันไป จะต้องทำตาม code ต่อไปนี้
e1 = cv2.getTickCount() # รันโปรแกรมของคุณ e2 = cv2.getTickCount() time = (e2 - e1) / cv2.getTickFrequency()
- อันดับต่อไปจะเป็นการเขียน function แบบง่ายๆขึ้นมาเพื่อทดสอบ มัธยฐาน กับ เลขคี่ จาก 5 ถึง 49
img1 = cv2.imread('somethingelse.jpg') e1 = cv2.getTickCount() for i in xrange(5,49,2): img1 = cv2.medianBlur(img1,i) e2 = cv2.getTickCount() t = (e2 - e1) / cv2.getTickFrequency() print t ## ผลลัพธ์ ที่ได้จะเป็น วินาที เช่น 0.0521107655
ค่าเริ่มต้นของการเพิ่มประสิทธิภาพใน OpenCV
- ใน OpenCV จะมีฟังก์ชั่นที่เข้ามาช่วยในการเพิ่มประสิทธิภาพของ Code ที่เราเขียน โดยจะสามารถตรวจสอบได้ว่าเราได้เปิดฟังก์ชั่นนั้นอยู่หรือไม่ โดย ใช้คำสั่ง cv2.useOptimized() เพื่อเช็คว่าเรา เปิด/ปิด ฟังก์ชั่นนั้นไว้หรือไม่ และ ใช้ cv2.setUseOptimized() เพื่อ เปิด/ปิด ใช้งานฟังก์ชั่น
- เริ่มต้นทดสอบ
- เข้า Terminal แล้วพิมพ์ pip install ipython เพื่อลง IPython
- หลังจากลงเสร็จก็เปิด Shell มาใช้โดยพิมพ์ว่า ipython บน Terminal
- จากนั้นก็เริ่มทดสอบ
#ตรวจสอบดูว่าได้เปิดฟังก์ชั่นเพิ่มประสิทธิภาพอยู่หรือไม่ import cv2 import numpy as np img1 = cv2.imread('messi5.jpg') In [5]: cv2.useOptimized() Out[5]: True In [6]: %timeit res = cv2.medianBlur(img,49) 10 loops, best of 3: 34.9 ms per loop # ผลลัพธ์ที่ออกมา # ปิดการเพิ่มประสิทธิภาพ In [7]: cv2.setUseOptimized(False) In [8]: cv2.useOptimized() Out[8]: False In [9]: %timeit res = cv2.medianBlur(img,49) 10 loops, best of 3: 64.1 ms per loop # ผลลัพธ์ที่ออกมา
วัดประสิทธิภาพด้วย IPython
- บางครั้ง คุณจะต้องเปรียบเทียบประสิทธิภาพของ กระบวนการทำงาน 2 กระบวนการ IPython จะช่วยให้ ได้รับผลลัพธ์ที่แม่นยำมากขึ้นในการวัดประสิทธิภาพของกระบวนการทำงาน
สำหรับตัวอย่างต่อไปนี้ เราจะทำตาม กระบวนการเพิ่มที่ดีกว่าเช่น ,x = 5; y = x**2, x = 5; y = x*x, x = np.uint8([5]); y = x*x or y = np.square(x) มีค่าเท่ากับเท่าไหร่ ????? เราจะมาหากันและหาเวลาที่ใช้ไปด้วย IPython Shell
In [10]: x = 5 In [11]: %timeit y=x**2 10000000 loops, best of 3: 73 ns per loop # ผลลัพธ์ที่ออกมา In [12]: %timeit y=x*x 10000000 loops, best of 3: 58.3 ns per loop # ผลลัพธ์ที่ออกมา In [15]: z = np.uint8([5]) In [17]: %timeit y=z*z 1000000 loops, best of 3: 1.25 us per loop # ผลลัพธ์ที่ออกมา In [19]: %timeit y=np.square(z) 1000000 loops, best of 3: 1.16 us per loop # ผลลัพธ์ที่ออกมา
- เราจะเห็นได้ว่า x = 5 ; y = x*x จะทำงานเร็วขึ้นประมาณ 20x เมื่อเทียบกับใช้ Numpy
เทคนิคการเพิ่มประสิทธิภาพ
- หลีกเลี่ยงการใช้ loop ใน Python โดยเฉพาะ ลูปที่มีการวนแบบ double/triple เพราะจะทำให้โปรแกรมช้าอย่างแน่นอน
- Vectorize เป็น Algorithm ที่เป็นไปได้สูงที่จะได้เพิ่มขอบข่าย เพราะ Numpy และ OpenCV ทั้งคู่นี่ เหมาะสำหรับการเพิ่มประสิทธิภาพให้กับงานที่เป็น เวกเตอร์
- หาประโยชน์จากไฟล์ cache
- อย่าสร้าง อาเรย์ (Array) ที่มีอยู่แล้ว ยกเว้นคุณจำเป็ฯต้องใช้งาน