TỐI ƯU HÓA XỬ LÝ CHƯƠNG TRÌNH potx

45 411 6
TỐI ƯU HÓA XỬ LÝ CHƯƠNG TRÌNH potx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

MỤC LỤC Chương 7 I. MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH 2 1. ĐẶT VẤN ĐỀ 2 2. HIỆN TƯỢNG NÚT CỔ CHAI 4 3. KỸ THUẬT ĐO THỜI GIAN THỰC HIỆN VÀ LƯU LẠI QUÁ TRÌNH HOẠT ĐỘNG (Profiling) 11 3.1. Đo thời gian tự động 11 3.2 . Kỹ thuật profiling – lưu lại quá trình thực hiện 13 3.3. Tập trung quan tâm vào các đoạn mã trọng tâm của chương trình 15 3.4. Biểu diễn trực quan số liệu thống kê hiệu năng thực hiện chương trình 16 4. CÁC CHIẾN LƯỢC TỐI ƯU HOÁ THỜI GIAN 17 4.1 . Sử dụng thuật toán hoặc cấu trúc dữ liệu tốt hơn 18 4.2. Sử dụng các chức năng tối ưu hóa trình biên dịch 18 4.2 . Tinh chỉnh mã nguồn 19 4.4. Không tối ưu hóa những gì không gây vấn đề 21 5. TIN CHỈNH MÃ NGUỒN 22 5.1. Tập hợp những biểu thức chung 22 5.2. Thay thế các thao tác chi phí cao bằng các thao tác chi phí thấp hơn 23 5.3. Trải rộng hay loại bỏ các vòng lặp 23 5.4. Lưu trữ lại các giá trị thường dùng 24 5.5. Xây dựng chức năng cấp phát bộ nhớ đặc dụng 25 5.6. Dùng bộ nhớ trung gian cho việc nhập và xuất dữ liệu 26 5.7. Xử lý riêng từng tình huống đặc biệt 26 5.8. Tính trước kết quả 27 5.9. Dùng các giá trị xấp xỉ 27 5.10 Viết lại mã nguồn bằng ngôn ngữ cấp thấp 27 6. TỐI ƯU HOÁ KHÔNG GIAN LƯU TRỮ 28 6.1. Tiến kiệm không gian bằng cách dùng kiểu dữ kiệu có kích thước nhỏ nhất 29 6.2. Không cần lưu trữ những gì có thể tính lại dễ dàng 29 7. ƯỚC LƯỢNG 31 II. NGUYÊN LÝ TRONG REFACTORING 35 1. ĐỊNH NGHĨA REFACTORING 35 2. TẠI SAO NÊN REFACTORING 36 2.1 Refactoring cải thiện thiết kế phần mềm 36 2.2 Refactoring làm phần mềm dễ hiểu 37 2.3 Refactoring giúp tìm Bugs 38 2.4 Refactoring giúp chương trình chạy nhanh hơn 38 3. KHI NÀO THỰC HIỆN REFACTORING 38 3.1 Refactor khi thêm chức năng 39 3.2 Refactor khi cần sửa lỗi (bug) 39 3.3 Refactor khi thực hiện duyệt chương trình 39 4. VẤN ĐỀ VỚI REFACTORING 40 4.1 Cơ sở dữ liệu (Database) 40 4.2 Thay đổi giao diện 41 5. REFACTORING VÀ HIỆU NĂNG XỬ LÝ 41 6. REFACTORING HỖ TRỢ TRONG VISUAL STUDIO 2005 42 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … Chương 7 I. MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH Bài viết này dựa trên nội dung chương 7 “Hiệu năng xử lý chương trình” (Chapter 7 – Performance) trích trong sách “The Practice of Programming” của tác giả Brian W. Kernighan va Rob Pike [1999]. Trong chương này, các tác giả trình bày một số vấn đề về tối ưu hóa xử lý chương trình, trong đó tập trung đi sâu phân tích các khía cạnh về tối ưu hóa thời gian xử lý, đồng thời trình bày một số kỹ thuật về tối ưu hóa không gian lưu trữ. 1. ĐẶT VẤN ĐỀ Vấn đề tối ưu hóa xử lý của chương trình được đặt ra từ rất lâu rồi. Trước đây, các nhà lập trình luôn cố gắng tối ưu hóa chương trình do các thế hệ máy tính bấy giờ có tốc độ xử lý còn chậm và giá thành cao. Ngày nay, máy tính đã trở nên phổ biến và tốc độ xử lý ngày càng tăng nhanh, do đó nhu cầu đặt ra đối với bài toán tối ưu hóa tuyệt đối chương trình đã giảm đi rất nhiều. Vậy ta có còn cần quan tâm đến vấn đề hiệu năng xử lý của chương trình nữa hay không? Trên thực tế, bài toán tối ưu hóa hiệu năng xử lý của chương trình vẫn rất có ý nghĩa trong cuộc sống. Tuy nhiên, vấn đề này chỉ thật sự cần được đặc biệt quan tâm khi bài toán cần được giải quyết thật sự có ý nghĩa quan trọng, trong khi chương trình hiện có để giải quyết bài toán này có tốc độ xử lý còn quá chậm so với yêu cầu thực tế, đồng thời ta có cơ sở để tối ưu hóa việc xử lý nhằm tăng tốc độ của chương trình mà vẫn đảm bảo tính đúng đắn, bền vững và trong sáng của chương trình. Một chương trình có tốc độ nhanh nhưng đưa ra đáp số chưa chính xác không giúp tiết kiệm được thời gian! Do đó, nguyên lý đầu tiên của tối ưu hóa là phải cân nhắc có cần tối ưu hóa chương trình hay không. Phải chăng chương trình hiện có đã đủ tốt rồi, không cần hoặc không thể tối ưu hóa thêm được nữa? Giả sử ta đã biết được cách mà một chương trình sẽ được sử dụng và môi trường thực hiện chương trình này, liệu việc tối ưu hóa nhằm tăng tốc độ xử lý chương trình có đem lại lợi ích gì hay không. Hầu hết những chương trình mà sinh viên viết trong quá trình học ở trường chỉ được sử dụng một vài lần, sau đó sẽ không sử dụng lại nữa, do đó, vấn đề tốc độ thường không được quan tâm. Vấn đề này thường cũng không ảnh hưởng và không cần quan tâm đối với hầu hềt các chương trình cá nhân, chẳng hạn như các công cụ, khung kiểm tra, thử nghiệm Ngược lại, đối với Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 2 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … các chức năng xử lý chính của một sản phẩm thương mại, chẳng hạn như thư viện đồ họa của phần mềm, vấn đề tối ưu hóa tốc độ xử lý có ý nghĩa hết sức quan trọng và cần được giải quyết. Như vậy, khi nào thì ta nên thử tìm cách tăng tốc xử lý chương trình và làm cách nào để thực hiện được điều này? Kết quả cụ thể mà ta mong muốn khi tiến hành việc tối ưu hóa là gì? Nội dung chương này sẽ trình bày các vấn đề về làm thế nào để chương trình chạy nhanh hơn (tối ưu hóa thời gian) hay sử dụng bộ nhớ tiết kiệm hơn (tối ưu hóa không gian lưu trữ). Tốc độ là vấn đề thường được quan tâm nhiều hơn nên ta sẽ đi sâu vào vấn đề này. Không gian lưu trữ (bộ nhớ chính, đĩa) thường ít được quan tâm hơn, nhưng cũng có ý nghĩa hết sức quan trọng, nên ta cũng sẽ tìm hiểu một số vấn đề liên quan đến tối ưu hóa không gian lưu trữ. Như ta đã biết Thuật toán và Cấu trúc Dữ liệu, chiến lược tốt nhất là sử dụng các thuật toán đơn giản nhất, rõ ràng nhất, và các cấu trúc dữ liệu phù hợp với bài toán cần giải quyết. Do đo, cần đo các thông số hiệu năng hoạt động để quyết định có cần tiến hành sửa đổi chương trình/thuật toán hay không; cần sử dụng các option của trình biên dịch để phát sinh mã thực hiện có tốc độ xử lý nhanh nhất; cần xác định nhũng phần nào trong chương trình khi được tối ưu hóa sẽ đem lại hiệu quả cao nhất cho toàn bộ chương trình; thực hiện lần lượt từng thay đổi cải tiến rồi sau đó đánh giá, phân tích trước khi tiến hành các thay đổi tiếp theo; đồng thời cần phải giữ lại phiên bản đơn giản chính xác (chưa tối ưu hóa nhưng chắc chắn chính xác) để kiểm tra kết quả so với các phiên bản cải tiến. Việc đo lường và thống kê là thành phần quan trọng của quy trình cải tiến hiệu năng chương trình vì suy luận và trực giác của con người có thể dẫn đến những định hướng sai lầm và cần phải được bổ sung bằng những công cụ đo thời gian thực hiện và lập sơ đồ thời gian của chương trình. Dựa vào các số liệu đo đạt và thống kê được thông qua các kỹ thuật như đo thời gian (timing command) và lưu lại quá trình hoạt động (profiler), ta có thể rút ra được những nhận xét và giải pháp nhằm tối ưu hóa chương trình. Việc cải tiến hiệu năng phải đi kèm với quá trình kiểm chứng chương trình (sử dụng kỹ thuật kiểm tra tự động, lưu vết các sửa đổi và phiên bản, thanh tra mã nguồn – code inspection, sử dụng các bộ dữ liệu thử nghiệm ) để đảm bảo chương trình sau khi sửa đổi vẫn đảm bảo tính đúng đắn và không làm mất đi các ưu điểm vốn có trong các phiên bản trước đó. Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 3 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … Nếu từ ban đầu chương trình được viết tốt với thuật toán hiệu quả thì có thể chỉ cần sửa đổi rất ít hoặc thậm chí không cần sửa đổi chương trình để cải tiến hiệu năng. Ngược lại, đối với những chương trình viết chưa tốt, tổ chức chưa hợp lý, không trong sáng, việc tối ưu hóa đòi hỏi phải sửa đổi rất nhiều, thậm chí phải tổ chức lại cấu trúc chương trình và viết lại từ đầu. 2. HIỆN TƯỢNG NÚT CỔ CHAI Đầu tiên, ta mô tả cách giải quyết hiện tượng nút cổ chai trong một chương trình quan trọng được sử dụng thường xuyên trong môi trường cục bộ. Các thư điện tử mà ta nhận được thông qua thiết bị gateway nối kết giữa mạng cục bộ với Internet. Mỗi ngày, có hàng vạn thư điện tử từ bên ngoài được gởi đến cho vài nghìn thành viên trong mạng cục bộ thông qua gateway và sau đó được chuyển đến từng người trong mạng nội bộ. Sự ngăn cách này cô lập mạng nội bộ với Internet và cho phép chỉ cần công bố một tên máy (là tên của gateway) cho tất cả mọi thành viên trong mạng nội bộ. Một trong số các dịch vụ gateway là lọc các “spam”, là các thư rác kèm theo các quảng cáo về những dịch vụ mà lợi ích chưa được kiểm chứng. Sau thời gian thử nghiệm ban đầu thành công, bộ lọc các “spam” được chính thức cài đặt và sử dụng như đặc tính không thể thiếu cho tất cả người dùng trong mạng nội bộ, và rồi rắc rối lập tức xuất hiện. Gateway, vốn cũ kỹ và thường rất bận, bị quá tải vì chương trình lọc chiếm quá nhiều thời gian – nhiều hơn hẳn so với thời gian cần thiết cho tất cả các thao tác xử lý khác đối với bức thư – đến mức độ hàng đợi thư bị đầy và việc truyền phát thư tín bị trì hoãn nhiều giờ trong khi hệ thống cố xoay sở để kịp phân phối thư. Trên đây là một ví dụ về vấn đề tốc độ thực hiện chương trình: chương trình không đủ nhanh để hoàn thành nhiệm vụ, và sự chậm trễ này tạo ra trở ngại cho người dùng. Do đó, chương trình cần phải được cải tiến, tối ưu hóa để có thể chạy nhanh hơn nhiều so với phiên bản hiện tại. Trước hết, ta hãy khảo sát cách hoạt động của bộ lọc “spam”. Mỗi thông điệp gửi tới được xem như một chuỗi ký tự đơn, và một bộ so mẫu ký tự kiểm tra chuỗi đó xem có chứa bất kỳ một cụm từ nào trong số các cụm từ thường gặp trong các “spam” hay không, chẳng hạn như: “Make millions in your spare time” (kiếm hàng triệu đồng trong thời gian rảnh của bạn) hay “XXX-rated” (các trang khiêu dâm). Các thông điệp có khuynh hướng lặp đi lặp lại, do đó, kỹ thuật này có hiệu quả đáng kể, và nếu như một thông điệp “spam” lọt lưới thì Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 4 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … một cụm từ đặc trưng cho “spam” đó sẽ được thêm vào danh sách các “spam” để chặn nó vào lần sau. Do không có sẵn một công cụ so sánh chuỗi vừa chạy nhanh vừa đáng tin cậy, ví dụ như grep, nên người ta viết ra một bộ lọc riêng dùng cho mục đích lọc các “spam”. Mã nguồn rất đơn giản; chương trình lọc “spam” sẽ tìm xem mỗi bức thông điệp có chứa một trong số các cụm từ (các mẫu) nào đó hay không: /* Hàm isspam: kiểm tra chuỗi thông điệp mesg có chứa spam nào không */ int isspam(char *mesg) { int i; for (i=0; i<npat; i++) if (strstr(mesg, pat[i]) != NULL) { printf("spam: match for '%s'\n", pat[i]); } } Làm thế nào ta có thể thực hiện đoạn chương trình trên nhanh hơn? Ta cần phải tìm kiếm chuỗi ký tự mẫu trong bức thông điệp, do đó, việc sử dụng hàm strstr của thư viện C là cách tốt nhất để tìm kiếm vì đây là hàm thư viện chuẩn được xây dựng hiệu quả. Sử dụng kỹ thuật lưu lại quá trình hoạt động (kỹ thuật profiling - sẽ được trình bày chi tiết trong phân sau . Kỹ thuật profiling – lưu lại quá trình thực hiện.), ta nhận thấy rằng hàm strstr có một số vấn đề chưa phù hợp khi sử dụng cho một bộ lọc spam. Trong trường hợp cụ thể này, việc thay đổi cách thức làm việc của hàm strstr có thể tăng hiệu quả hoạt động của hệ thống. Hàm strstr được cài đặt lại như sau: /* Hàm strstr : dùng hàm strchr để tìm kiếm kí tự đầu tiên */ char* strstr(const char *s1, const char *s2) { int n; Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 5 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … n = strlen(s2); for (;;) { s1 = strchr(s1, s2[0]); if (s1 == NULL) return NULL; if (strncmp(s1, s2, n) == 0) return (char*) s1; s1++; } } Đoạn chương trình trên được viết lại hướng tới mục tiêu hiệu quả tốc độ. Trên thực tế, đoạn lệnh này chạy nhanh nếu dùng cho một mục đích tiêu biểu nào đó, vì chỉ dùng các hàm được tối ưu hóa cao để thực hiện công việc. Đoạn chương trình này gọi hàm strchr để tìm vị trí tiếp theo của ký tự đầu tiên trong chuỗi, sau đó gọi hàm strncmp để kiểm tra phần còn lại của chuỗi có so khớp với phần còn lại của chuỗi mẫu. Như vậy, đoạn chương trình này sẽ bỏ qua một phần lớn của bức thông điệp để tìm ký tự đầu tiên của chuỗi mẫu, rồi quét nhanh để kiểm tra phần còn lại. Thế nhưng, tại sao tốc độ thực hiện chương trình khi sử dụng hàm strstr được cải tiến vẫn còn quá chậm? Hiện tượng trên có thể được lý giải bằng các lý do chính sau đây. Trước tiên, hàm strncmp lấy chiều dài chuỗi mẫu bằng strlen làm tham số đầu vào. Thế nhưng vì chuỗi mẫu có chiều dài cố định nên việc tính lại độ dài chuỗi mẫu khi xử lý mỗi thông điệp là không cần thiết . Thứ hai, hàm strncmp có chứa một vòng lặp phức tạp. Thực tế, không những hệ thống phải so sánh từng byte của hai chuỗi mà phải tìm byte cuối ‘\0’ trên cả hai chuỗi trong khi vẫn đếm lùi tham số chiều dài. Vì chiều dài của tất cả các chuỗi đều đã biết trước (dù không cần dùng tới hàm strncmp) nên sự phức tạp này là không cần thiết. Ta thấy rằng phép đếm là cần thiết, nhưng việc kiểm tra byte ‘\0’ sẽ lãng phí nhiều thời gian. Thứ ba, hàm strnchr cũng phức tạp, bởi vì đồng thời vừa tìm ký tự và kiểm tra byte ‘\0’ kết thúc bức thông điệp. Trong một lần gọi hàm isspam, bức thông điệp là cố định, vì vậy thời gian dùng để kiểm tra byte ‘\0’ là lãng phí vì ta đã biết chính xác bức thông điệp kết thúc ở đâu. Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 6 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … Cuối cùng, dù cho hàm strncmp, strchr, và strlen đều rất hiệu quả khi làm việc độc lập, tổng thời gian cần để gọi các hàm này cũng xấp xỉ với thời gian tính toán của chúng. Sẽ hiệu quả hơn nếu làm mọi việc bằng chỉ một hàm strstr được viết lại thật cẩn thận và tránh gọi tất cả những hàm khác. Những vấn đề thuộc dạng này chính là một nguồn gốc chung làm chậm tốc độ thực hiện chương trình – một thủ tục hoặc một phương thức giao tiếp làm việc tốt trong một tình huống điển hình nhưng lại thực hiện kém hiệu quả trong tình huống bất thường xảy ra trở thành vấn đề trung tâm của chương trình. Hàm strstr có sẵn thực hiện tốt khi chuỗi mẫu và chuỗi cần tìm ngắn và thay đổi ở mỗi lần hàm được gọi. Nhưng khi chuỗi cần tìm dài và cố định thì thời gian thời gian xử lý lại bị lãng phí quá nhiều. Từ những nhận xét trên đây, ta quyết định viết lại hàm strstr để xử lý trên chuỗi mẫu cùng với chuỗi thông điệp nhằm tìm ra chỗ so khớp mà không cần gọi các thủ tục con. Khả năng thực hiện khi thực hiện giải pháp này hoàn toàn có thể dự đoán được: chương trình có thể hơi chậm trong một số trường hợp cá biệt, nhưng lại rất nhanh trong việc lọc các “spam” và quan trọng nhất là không bao giờ chạy quá lâu. Để kiểm tra lại tính đúng đắn của bản cài đặt mới cũng như tốc độ thực hiện của chương trình mới, ta xây dựng một bộ kiểm chứng tốc độ thực hiện. Bộ thử này không chỉ gồm các ví dụ đơn giản như tìm một từ trong câu, mà còn gồm cả một số trường hợp đặc biệt, ví dụ như tìm chuỗi mẫu chỉ có một ký tự ‘x’ trong chuỗi có một ngàn ký tự ‘e’, và chuỗi mẫu có một ngàn ký tự ‘x’ trong một chuỗi chỉ có một ký tự ‘e’. Những trường hợp đặc biệt như vậy là phần chính trong việc đánh giá khả năng thực hiện. Thư viện được cập nhật bằng hàm strstr mới và bộ lọc “spam” chạy nhanh hơn 30%, đây là một kết quả cải tiến đáng kể cho việc viết lại. Tuy nhiên, tốc độ thực hiện vẫn còn quá chậm. Khi giải quyết các khó khăn, điều quan trọng là xác định đúng vấn đề cần giải quyết. Cho đến nay, ta đang đặt vấn đề tìm cách nhanh nhất để truy soát một chuỗi ký tự mẫu trong một chuỗi ký tự. Tuy nhiên, thật ra thì vấn đề là tìm kiếm một tập hợp lớn, cố định các chuỗi ký tự mẫu trong một chuỗi ký tự dài thay đổi. Trong trường hợp đó, hàm strstr chưa thật sự là giải pháp đúng. Cách hiệu quả nhất để làm cho một chương trình chạy nhanh hơn là dùng một giải thuật tốt hơn. Bây giờ, khi đã nhìn rõ hơn vấn đề cần giải quyết, ta cần suy nghĩ xem thuật toán nào sẽ làm việc tốt nhất. Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 7 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … Xét vòng lặp cơ bản: for (i=0; i < npat; i++) if (strstr(meg, pat[i]) != NULL) return 1; Vòng lặp này duyệt qua bức thông điệp npat lần độc lập với nhau; giả sử đoạn lệnh không tìm ra bất kỳ sự so khớp nào, đoạn lệnh này đã phân tích từng byte của bức thông điệp npat lần trong strlen(mesg)*npat phép so sánh. Một cách tiếp cận tốt hơn là đảo ngược vòng lặp, quét qua bức thông điệp một lần ở vòng lặp ngoài trong khi tìm tất cả các chuỗi mẫu song song ở vòng lặp trong: for (j=0; mesg[j] != '\0'; j++) if (có chuỗi mẫu nào có phần đầu trùng với ký tự đầu của mesg[j]) return 1; Sự cải thiện tốc độ bắt nguồn từ cách nhìn hết sức đơn giản. Để nhận ra liệu có chuỗi mẫu nào so khớp với bức thông điệp ở vị trí j không, ta không cần phải xét tất cả các chuỗi mẫu mà chỉ cần xét các chuỗi có cùng ký tự đầu tiên với mesg[j]. Nói cách khác, với 52 ký tự chữ hoa và chữ thường, ta chỉ cần thực hiện strlen(mesg)*npat/52 phép so sánh. Vì các chữ cái không phân bố đều, có nhiều từ bắt đầu bằng ký tự ‘s’ hơn là bằng ký tự ‘x’, ta không thể kết luận rằng giải pháp này cải thiện tốc độ nhanh hơn gấp 52 lần phiên bản trước, tuy nhiên, rõ ràng việc tối ưu hóa này đem lại kết quả rất đáng kể. Để thực hiện, ta xây dựng một bảng băm dùng ký tự đầu tiên của chuỗi mẫu làm khóa. Dựa vào một vài tính toán trước để xây dựng một bảng những chuỗi mẫu bắt đầu với từng ký tự, hàm isspam vẫn được viết ngắn gọn như sau: int patlen[NPAT]; /* mảng chiều dài của các chuỗi mẫu */ int starting[UCHAR_MAX+1][NSTART]; /* danh sách các chuỗi mẫu bắt bằng ký tự tương ứng */ int nstarting[UCHAR_MAX+1]; /* số chuỗi mẫu bắt đầu bằng ký tự tương ứng */ Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 8 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … /* Hàm isspam: kiểm tra chuỗi thông điệp mesg có chứa spam nào không */ int isspam(char *mesg) { int i, j, k; unsigned char c; for (j=0; (c = mesg[j]) != '\0'; j++) { for (i=0; i<nstarting[c]; i++) { k = starting[c][i]; if (memcmp(mesg+j, pat[k], patlen[k]) == 0) { printf("spam: match for ‘%s’\n", pat[k]); return 1; } } } return 0; } Với mỗi ký tự ‘c’, mảng hai chiều starting[c][] chứa danh sách các chuỗi mẫu bắt đầu bằng ký tự ‘c’. Mảng nstarting[c] ghi nhận bao nhiêu chuỗi mẫu bắt đầu bằng ký tự ‘c’. Nếu không có các bảng đó, vòng lặp trong sẽ chạy từ 0 đến npat, khoảng 1000, thay vì chỉ chạy từ 0 đến khoảng 20. Còn phần tử mảng patlen[k] chứa kết quả tính toán trước của strlen(pat[k]). Hình dưới đây phác họa các cấu trúc dữ liệu trên dùng một tập hợp ba chuỗi mẫu bắt đầu bằng ký tự ‘b’: Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 9 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … 3 . . . . . . 1 7 3 5 9 7 4 9 1 4 b u y ! b i g b u c k s b e s t p i c t u r e s ! [ ' b ' ] [ 1 7 ] [ 3 5 ] [ 9 7 ] n s t a r t i n g : s t a r t i n g : p a t l e n : p a t : Hình SEQ Hình \* ARABIC \s 1 1: Minh họa các cấu trúc dữ liệu được sử dụng để lưu trữ thông tin của các chuỗi ký tự mẫu Dưới đây là đoạn chương trình để xây dựng các bảng chứa thông tin các chuỗi mẫu: int i; unsigned char c; for (i=0; i<npat; i++) { c = pat[i][0]; if (nstarting[c] >= NSTART) eprintf(" too many patterns (>=%d) begin '%c'", NSTART, c); starting[c][nstarting[c]++] = i; patlen[i] = strlen(pat[i]); } Phụ thuộc vào dữ liệu nhập, bộ lọc “spam” bây giờ cải tiến chạy nhanh hơn từ 5 đến 10 lần khi dùng hàm strstr, và nhanh hơn từ 7 đến 15 lần khi dùng phương pháp đầu tiên. Tốc độ thực hiện không thể đạt được mức nhanh hơn 52 Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 10 [...]... độ xử lý cho các chương trình kiểm chứng hầu như không có giá trị Đối với chương trình hoạt động liên tục nhiều năm, bạn nên tối ưu hóa tất cả những gì có thể được Thậm chí, sau nhiều tháng sử dụng chương trình, bạn có thể tiếp tục việc cải tiến tối ưu hóa chương trình nếu giải pháp mới có thể giúp tăng 10% tốc độ chương trình Các chương trình có tính cạnh tranh như trò chơi, trình biên dịch, xử lý. .. định, các trình biên dịch C và C++ thường không sử dụng nhiều các chức năng tối ưu hóa cho chương trình Các tùy chọn trong trình biên dịch cho phép lập trình viên quyết định sử dụng hay không các chức năng tối ưu hóa của trình biên dịch Lập trình viên thường cần phải kích thước tường minh tùy chọn tối ưu hóa mã nguồn của trình biên dịch sau khi đã kiểm lỗi xong chương trình Việc tối ưu hóa thông qua... các chức năng tối ưu hóa trình biên dịch Chúng ta có thể cải thiện đáng kể tốc độ xử lý chương trình một cách đơn giản mà không cần sửa đổi bất kỳ một dòng mã nguồn nào bằng cách sử dụng hiệu quả các chức năng tối ưu hóa có sẵn trong trình biên dịch Các trình biên dịch hiện đại ngày nay có khả năng tối ưu hóa hiệu quả các đoạn mã nguồn chương trình Việc sử dụng các chiến lược tối ưu hóa trình biên dịch... 18 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … so trùng khớp cuối cùng có thời gian thi hành ban đầu là 8.1 giây giảm xuống còn 5.9 giây khi sử dụng chức năng tối ưu hóa của trình biên dịch (mức độ cải thiện là 25%) Ngược lại, ở phiên bản dùng hàm strstr đã sửa đổi, việc tối ưu hóa không đem lại một cải thiện nào bởi lẽ hàm strstr đã được tối ưu hóa khi đưa vào thư viện: bộ tối ưu hóa chỉ áp dụng... không có những ưu điểm này Biểu diễn nhị phân thường được dùng để tăng tốc xử lý nhưng chúng ta nên cân nhắc khi sử dụng Bài toán tối ưu hóa không gian lưu trữ và thời gian xử lý thường có khuynh hướng ngược chiều nhau Nếu tập trung nhằm tối ưu hóa không gian lưu trữ thường làm giảm tốc độ xử lý Chúng ta thử xét một ứng dụng chuyển một ảnh có kích thước lớn từ một chương trình này sang chương trình khác... một sự tối ưu hóa thiển cận Ngày nay, vấn đề khan hiếm bộ nhớ đã được giải quyết Bộ nhớ chính cũng như bộ nhớ phụ đã trở nên ngày càng rẻ một cách đáng ngạc nhiên Do vậy, hướng tiếp cận đầu tiên đối với vấn đề tối ưu hóa không gian lưu trữ cũng giống như đốivới vấn đề tối ưu hóa tốc độ xử lý, đó là không cần quan tâm đến việc tối ưu hóa không gian! Tuy nhiên, vẫn có một số trường hợp cần tối ưu hóa không... _malloc 14 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … Bảng 1: Bảng thống kê quá trình thực hiện chương trình spamtest nguyên thủy Rõ ràng hàm strchr và hàm strncmp, cả hai do hàm strstr gọi, chiếm hầu hết thời gian thực hiện chương trình Nhận xét của tác giả Knuth hoàn toàn chính xác: chỉ một phần nhỏ của chương trình đã chiếm gần hết thời gian chạy chương trình Khi một chương trình lần đầu tiên được... kế chương trình sẽ bị hư tổn Khi thay đổi chương trình – thay đổi hiện thực hóa mục tiêu ngắn hạn hay sự thay đổi không được hiểu thấu đáo thiết kế chương trình – chương trình mất cấu trúc Chương trình sẽ trở nên khó để hiểu thiết kế bởi việc đọc chương trình Refactoring sẽ làm gọn chương trình Công việc được thực hiện chuyển đổi chút ít những gì thực sự không để đúng chổ Việc mất cấu trúc chương trình. .. điều chỉnh 3 dòng của chương trình Nguyễn Thị Thanh Trúc – Mai Xuân Hùng 20 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … 4.4 Không tối ưu hóa những gì không gây vấn đề Đôi khi sự tinh chỉnh mã nguồn không đem lại kết quả gì bởi vì được áp dụng đối với những chỗ không phù hợp Cần chắc chắn rằng đoạn mã đang được tối ưu hóa thật sự là chỗ chiếm nhiều thời gian chạy trong chương trình Câu chuyện sau đây... trong chương trình chứ không phải vào các thư viện hệ thống Tuy nhiên, một số trình biên dịch có các bộ tối ưu hóa toàn cục có khả năng phân tích toàn bộ chương trình tìm những chỗ còn có thể cải thiện được Nếu một trình biên dịch như thế có trong hệ thống của bạn, hãy thử sử dụng; điều này có thể giúp giảm được một vài chu kỳ xử lý Một điều cần phải hiểu rõ là càng cho phép trình biên dịch tối ưu hóa . giả trình bày một số vấn đề về tối ưu hóa xử lý chương trình, trong đó tập trung đi sâu phân tích các khía cạnh về tối ưu hóa thời gian xử lý, đồng thời trình bày một số kỹ thuật về tối ưu hóa. REFACTORING VÀ HIỆU NĂNG XỬ LÝ 41 6. REFACTORING HỖ TRỢ TRONG VISUAL STUDIO 2005 42 MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH … Chương 7 I. MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH Bài viết này. ưu hóa không gian lưu trữ. 1. ĐẶT VẤN ĐỀ Vấn đề tối ưu hóa xử lý của chương trình được đặt ra từ rất lâu rồi. Trước đây, các nhà lập trình luôn cố gắng tối ưu hóa chương trình do các thế hệ

Ngày đăng: 13/07/2014, 07:20

Từ khóa liên quan

Mục lục

  • Chương 7 I. MỘT SỐ VẤN ĐỀ TỐI ƯU HOÁ XỬ LÝ CHƯƠNG TRÌNH

    • 1. ĐẶT VẤN ĐỀ

    • 2. HIỆN TƯỢNG NÚT CỔ CHAI

    • 3. KỸ THUẬT ĐO THỜI GIAN THỰC HIỆN VÀ LƯU LẠI QUÁ TRÌNH HOẠT ĐỘNG (Profiling)

      • 3.1. Đo thời gian tự động

      • 3.2 . Kỹ thuật profiling – lưu lại quá trình thực hiện.

      • 3.3. Tập trung quan tâm vào các đoạn mã trọng tâm của chương trình.

      • 3.4. Biểu diễn trực quan số liệu thống kê hiệu năng thực hiện chương trình

      • 4. CÁC CHIẾN LƯỢC TỐI ƯU HOÁ THỜI GIAN

        • 4.1 . Sử dụng thuật toán hoặc cấu trúc dữ liệu tốt hơn

        • 4.2. Sử dụng các chức năng tối ưu hóa trình biên dịch

        • 4.2 . Tinh chỉnh mã nguồn

        • 4.4. Không tối ưu hóa những gì không gây vấn đề

        • 5. TIN CHỈNH MÃ NGUỒN

          • 5.1. Tập hợp những biểu thức chung.

          • 5.2. Thay thế các thao tác chi phí cao bằng các thao tác chi phí thấp hơn.

          • 5.3. Trải rộng hay loại bỏ các vòng lặp.

          • 5.4. Lưu trữ lại các giá trị thường dùng

          • 5.5. Xây dựng chức năng cấp phát bộ nhớ đặc dụng

          • 5.6. Dùng bộ nhớ trung gian cho việc nhập và xuất dữ liệu.

          • 5.7. Xử lý riêng từng tình huống đặc biệt

          • 5.8. Tính trước kết quả

          • 5.9. Dùng các giá trị xấp xỉ

          • 5.10 Viết lại mã nguồn bằng ngôn ngữ cấp thấp

Tài liệu cùng người dùng

Tài liệu liên quan