2010-10-21 46 views
7

Tôi có một câu hỏi liên quan đến tốc độ dereferencing con trỏ. Tôi có cấu trúc như vậy:Tốc độ dereferencing C cấu trúc con trỏ

typedef struct _TD_RECT TD_RECT; 
struct _TD_RECT { 
    double left; 
    double top; 
    double right; 
    double bottom; 
}; 

Câu hỏi của tôi là, câu hỏi nào trong số này sẽ nhanh hơn và tại sao?


TRƯỜNG HỢP 1:

TD_RECT *pRect; 
... 
for(i = 0; i < m; i++) 
{ 
    if(p[i].x < pRect->left) ... 
    if(p[i].x > pRect->right) ... 
    if(p[i].y < pRect->top) ... 
    if(p[i].y > pRect->bottom) ... 
} 

TRƯỜNG HỢP 2:

TD_RECT *pRect; 
double left = pRect->left; 
double top = pRect->top; 
double right = pRect->right; 
double bottom = pRect->bottom; 
... 
for(i = 0; i < m; i++) 
{ 
    if(p[i].x < left) ... 
    if(p[i].x > right) ... 
    if(p[i].y < top) ... 
    if(p[i].y > bottom) ... 
} 

Vì vậy, trong trường hợp 1, vòng lặp được trực tiếp dereferencing con trỏ pRect để có được sự so sánh giá trị. Trong trường hợp 2, các giá trị mới được thực hiện trên không gian cục bộ của hàm (trên ngăn xếp) và các giá trị được sao chép từ pRect đến các biến cục bộ. Thông qua một vòng lặp sẽ có nhiều so sánh.

Trong tâm trí của tôi, họ sẽ không kém chậm, bởi vì các biến địa phương cũng là một tài liệu tham khảo bộ nhớ trên stack, nhưng tôi không chắc chắn ...

Ngoài ra, nó sẽ là tốt hơn để giữ tham khảo p [] theo chỉ mục, hoặc tăng p bởi một phần tử và dereference nó trực tiếp mà không có một chỉ mục.

Bất kỳ ý tưởng nào? Cảm ơn :)

+13

Bỏ phí thời gian của bạn với tối ưu hóa sớm mà rất có thể sẽ không tạo ra một smidgen khác biệt. –

+1

có lẽ là phần của một vấn đề về mùi, nhưng nếu có, tại sao không đo lường nó? – kenny

+0

Đối với Win32, tôi có thể sử dụng GetTickCount() để đo thời gian trước và sau khi gọi vòng lặp để đo tốc độ, hoặc có cách nào tốt hơn không? – oldSkool

Trả lời

1

Tôi nghĩ rằng trường hợp thứ hai có khả năng nhanh hơn vì bạn không dereferencing con trỏ để pRect trên mỗi vòng lặp lặp đi lặp lại. Thực tế, một trình biên dịch tối ưu hóa có thể nhận thấy điều này và có thể không có sự khác biệt trong mã được tạo ra, nhưng khả năng pRect là bí danh của một mục trong p [] có thể ngăn chặn điều này.

12

Có thể bạn sẽ thấy nó sẽ không tạo sự khác biệt với các trình biên dịch hiện đại. Hầu hết trong số họ có thể sẽ thực hiện loại trừ phổ biến subexpresion của các biểu thức mà không thay đổi trong vòng lặp. Sẽ không khôn ngoan khi giả định rằng có một ánh xạ một-một đơn giản giữa các câu lệnh C và mã assembly của bạn. Tôi đã nhìn thấy gcc bơm ra mã mà sẽ đưa kỹ năng lắp ráp của tôi để xấu hổ.

Nhưng đây không phải là câu hỏi C hoặc C++ vì tiêu chuẩn ISO không ủy quyền cách thực hiện. Cách tốt nhất để kiểm tra chắc chắn là tạo mã lắp ráp với một cái gì đó như gcc -S và kiểm tra hai trường hợp một cách chi tiết.

Bạn cũng sẽ nhận được lợi tức đầu tư nhiều hơn nếu bạn tránh xa loại tối ưu hóa vi mô này và tập trung nhiều hơn vào cấp độ macro, chẳng hạn như chọn thuật toán và như vậy.

Và, như với tất cả các câu hỏi tối ưu hóa, số đo , đừng đoán! Có quá nhiều biến có thể ảnh hưởng đến nó, vì vậy bạn nên đánh giá các phương pháp tiếp cận khác nhau trong môi trường đích và với dữ liệu thực tế.

+0

Tôi hỏi vì hàm tôi viết là cắt đa giác cho bản đồ vectơ chứa hàng triệu của đỉnh ... bất kỳ tốc độ nào tôi có thể ép ra khỏi nó sẽ giúp đỡ bởi vì tôi cần phải cắt từng phần đến 1 khu vực độ. – oldSkool

+2

Tốt thôi. Điều chính xác cần làm là chạy các tiêu chuẩn thực tế vì nó phụ thuộc vào một số lượng lớn các yếu tố, rất ít trong số chúng ta biết. Ở mức tối thiểu, máy mục tiêu của bạn, trình biên dịch, CPU, các vấn đề kiến ​​trúc khác như bộ nhớ và các hệ thống con I/O, thành phần dữ liệu của bạn, mức tối ưu hóa và vv. – paxdiablo

+0

Bạn có hàng triệu người trong số họ, hãy xem nhận xét của tôi bên dưới. Tạo chỉ mục trên bản đồ vectơ của bạn (nghĩa là p?), Được sắp xếp theo x và theo y. (Liệu nó vẫn còn khá tĩnh?). Hoặc sắp xếp nó trên x và có chỉ mục trên y. Sử dụng tìm kiếm nhị phân để tìm tất cả x right, tất cả y bottom. Vì vậy, nếu bạn đã nói 4 triệu đó là 22 so sánh cho mỗi, 88 tổng số, thay vì 16 triệu bạn có ngay bây giờ! – CashCow

0

Trình biên dịch tối ưu hóa sẽ thấy rằng truy cập cấu trúc là bất biến vòng lặp và do đó, hãy thực hiện Loop-invariant code motion, làm cho hai trường hợp của bạn trông giống nhau.

3

Nó không có khả năng là một sự khác biệt cực kỳ hiệu quả. Bạn có thể lập hồ sơ làm mỗi tùy chọn nhiều lần và xem. Đảm bảo bạn đã tối ưu hóa trình biên dịch được đặt trong thử nghiệm.

Liên quan đến việc lưu trữ đôi, bạn có thể nhận được một số hit hiệu suất bằng cách sử dụng const. Làm thế nào lớn là mảng của bạn?

Liên quan đến việc sử dụng số học con trỏ, điều này có thể nhanh hơn, có.

Bạn có thể ngay lập tức tối ưu hóa nếu bạn biết còn lại < ngay trong trực tràng của bạn (chắc chắn nó phải là). Nếu x < còn lại, nó cũng không thể là> phải để bạn có thể đặt "khác".

Tối ưu hóa lớn của bạn, nếu có, sẽ không phải lặp qua tất cả các mục trong mảng của bạn và không phải thực hiện 4 lần kiểm tra tất cả các mục đó. Ví dụ: nếu bạn đã lập chỉ mục hoặc sắp xếp mảng của mình trên x và y, bạn có thể sử dụng tìm kiếm nhị phân để tìm tất cả các giá trị có x < bên trái và lặp qua chỉ những giá trị đó.

0

Tôi sẽ ngạc nhiên nếu ngay cả một trình biên dịch hoàn toàn không được tối ưu hóa (- O0) sẽ tạo ra mã số khác nhau cho hai trường hợp được trình bày. Để thực hiện bất kỳ thao tác nào trên một bộ xử lý hiện đại, dữ liệu cần phải được nạp vào thanh ghi. Vì vậy, ngay cả khi bạn khai báo các biến tự động, các biến này sẽ không tồn tại trong bộ nhớ chính mà đúng hơn là trong một trong các thanh ghi dấu chấm động của bộ xử lý. Điều này sẽ đúng ngay cả khi bạn không tự khai báo các biến và do đó tôi không mong đợi sự khác biệt nào trong mã máy được tạo ngay cả khi bạn khai báo các biến tạm thời trong mã C++ của bạn.

Nhưng như những người khác đã nói, biên dịch mã thành lắp ráp và xem cho chính mình.

Các vấn đề liên quan