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) ที่มีอยู่แล้ว ยกเว้นคุณจำเป็ฯต้องใช้งาน