Hướng dẫn tăng tốc python
Trụ sở chính: Show Văn phòng: Số 27-3RD, Sunrise D, The Manor Central Park, đường Nguyễn Xiển, phường Đại Kim, quận Hoàng Mai, TP. Hà Nội. Liên hệ truyền thông: 0929.536.185 Email: [email protected] Chịu trách nhiệm nội dung: Ông Trần Anh Tú TEK4.VN giữ bản quyền nội dung trên website này. Cấm sao chép dưới mọi hình thức nếu không có sự chấp thuận bằng văn bản.
Python là ngôn ngữ lập trình phổ biến nhất hiện nay. Dễ học, ứng dụng đa dạng, thư viện nhiều, áp dụng cho xử lý, phân tích dữ liệu tuyệt vời, làm AI, Machine Learning, Deep Learning mà không dùng Python nhưng đi đáng bóng mà không mang bóng. Tuy nhiên nhược điểm của Python là chạy chậm, rất chậm. Những đoạn lệnh nào chạy nhanh, thực ra là Python gọi vào thư viện bao lấy code C hoặc C++ thuần, ví dụ như numpy, pandas, opencv, tensorflow, yolo... Để thí nghiệm, làm dự án prototype chúng ta có thể dùng Python thuần, nhưng khi lên production cần tối ưu tốc độ, đôi khi là bảo mật code chúng ta không thể máy móc dùng Python mà cần sử dụng thêm kỹ thuật khác nữa. Bài viết này giới thiệu Cython và tận dụng tối đa các thư viện gốc C/C++ để tăng tốc độ. Ví dụ minh hoạ sử dụng OpenCV để mở một ảnh con báo gấm sau đó dùng 2 vòng lặp for lồng nhau để chỉnh độ xám từng điểm ảnh. Ví dụ ảnh có kích thước 769 x 960 thì chúng ta phải thực hiện 738,240 động tác chỉnh độ xám cho từng điểm ảnh.
Bước 1: Hãy clode demo code vềBạn cần phải có Python 3.7.x cài sẵn trên máy tính
Nếu bạn thấy hiện ra hình ảnh con báo gấm là ok ! Code nguyên gốc chưa tối ưu đây. Code sử dụng thư viện numpy, cv2, math, time.
Kết quả chạy là 0.659 giây. Bước 2: Thay np.arange và range, gói đoạn lệnh thay đổi contrast vào hàmỞ đoạn code trên, chúng ta có thể thay thế np.arange bằng cú pháp thuần Python là range. Nhờ động tác này chúng ta giảm phụ thuộc vào numpy.
Bước 3: Sử dụng CythonĐể sử dụng Cython, chúng ta cần tách hàm adjust_contrast ra một file contrast.pyx, file này hoàn toàn không nhúng code C, hay sử dụng biến kiểu strongly type
Ngoài ra thêm một file setup.py nội dung như sau.
Để biên dịch file contrast.pyx chỉ cần gõ lệnh. Kết quả sẽ biên dịch ra file contrast.cpython-37m-darwin.so
Chạy file contrast3.py có import contrast biên dịch bằng Cython ở bước trên
Kết quả chạy sau khi dùng Cython là 0.2728 second. Nhanh hơn cách ở cách bước 1 là 2.4 lần, cách bước 2 là 1.3 lần Bước 4: Thay hàm Python bằng hàm kiểu CChúng ta cải tiến contrast.pyx thành contrast_c.pyx và setup_c.pyx
Thời gian chạy rút xuống còn 0.0794 giây, nhanh hơn cách 1 là 8.3 lần. Rõ ràng tốc độ cải thiện khá nhiều Bước 5: Dùng hàm ceil C thay vì hàm ceil của PythonNếu ngó vào file contrast_c.pyx bước 3, chúng ta thấy nó dùng một hàm math.ceil của Python. Như vậy code biên dịch ra C gọi vào module math của Python. Đây là cách rất thiếu tối ưu, hay tối ưu không dứt điểm. Chúng ta cần bỏ càng nhiều phụ thuộc vào các
module Python trong file pyx, ngược lại phải tận dụng tối đa các thư viện C, C++ thuần. Thay vì dùng hàm math.ceil của python chúng ta dùng hàm ceil của C.
Code sau khi cải tiến, chạy chỉ còn 0.0003 giây. Tốc độ tăng lên 2196 lần so với cách đầu tiên. Tại sao tốc độ lại tăng dữ dội đến vậy 2 vòng lặp lồng nhau sẽ khiến một lệnh chạy chậm chạy gấp lên M x N lần. Nếu ảnh cỡ 4 Mega Pixels thì hàm kém tối ưu sẽ là thảm hoạ. Bước 6: Sử dụng Numpy nhân ma trậnĐây là cách đúng đắn khôn ngoan nhất bởi Numpy có sẵn hàm nhân ma trận cực kỳ tối ưu. Code lại hết sức đơn giản
Tổng kết
Cảm ơn bạn Vũ Hữu Tiệp đã chỉ ra cách xử lý nhân ma trận bằng Numpy ! |