2013-06-13 28 views
7

Đây là mã C:Trình biên dịch sẽ tối ưu hóa câu lệnh có điều kiện trong vòng lặp bằng cách di chuyển nó ouside vòng lặp?

struct node{ 
    void *value; 
    struct node *next; 
}; 

void g(void *p){ 
    /*...*/ 
} 

void f(struct node *head, const int ok){ 
    struct node *p=head; 

    while (p){ 
     /* ... 
      code 1 
      ... 
     */ 
     if (ok!=0){ 
      g(p->value); 
     } 
     p=p->next; 
    } 
} 

tôi đã sử dụng gcc để biên dịch mã này. Nếu tôi biên soạn với -O, nó sẽ tối ưu hóa chức năng f như thế này:

void f(struct node *head, const int ok){ 
    struct node *p=head; 

    if (ok!=0){ 
     while (p){ 
      /* ... 
       code 1 
       ... 
      */ 
      g(p->value); 
      p=p->next; 
     } 
    } 
    else{ 
     while (p){ 
      /* ... 
       code 1 
       ... 
      */ 
      p=p->next; 
     } 
    } 
} 
+0

Nó có thể nhấc nó ra khỏi vòng lặp. Tại sao không kiểm tra? – Hasturkun

+1

Bạn có thể hướng dẫn hầu hết các trình biên dịch để hiển thị mã lắp ráp. Vì vậy, bạn có thể kiểm tra xem bản thân bạn khá dễ dàng. – Joey

+1

"Trình biên dịch sẽ tối ưu hóa XYZ" - tốt, bạn đã suy ra gì từ asembly được tạo ra (mà bạn ** đã kiểm tra trước khi hỏi, phải không?) –

Trả lời

15

Đó rất nhiều sẽ phụ thuộc vào độ lớn /* code 1 */ là. Nếu nó là rất nhỏ, nó có thể. Nhưng nếu nó là bất cứ điều gì trên một vài dòng, nó có lẽ sẽ không. Sao chép một số lượng lớn mã cho mỗi if sẽ có tác động khủng khiếp đến hiệu suất. Trong thực tế, điều đó có thể xảy ra với tối ưu hóa rất tích cực và chắc chắn không chỉ với -O. Từ trang người đàn ông của gcc (tôi nhấn mạnh):

-O
-O1 ...

Với -O, trình biên dịch sẽ cố gắng để giảm mã kích thước thời gian thực hiện, mà không thực hiện bất kỳ tối ưu hóa nào mất nhiều thời gian biên dịch.

Vì vậy, việc giảm mã cũng là một phần của tối ưu hóa.

-O2 Tối ưu hóa nhiều hơn. GCC thực hiện gần như tất cả các tối ưu hóa được hỗ trợ mà không liên quan đến một sự cân bằng tốc độ không gian. So với -O, tùy chọn này tăng cả thời gian biên dịch và hiệu suất của mã được tạo.

Vì vậy, -O2 cũng không làm những gì bạn muốn.

-O3 Tối ưu hóa hơn nữa. -O3 bật tất cả các tối ưu hóa được chỉ định bởi -O2 và cũng bật các tùy chọn -finline-functions, -funswitch-loops, -fpredictive-commoning, -fgcse-after-reload, -ftree-vectorize-fipa-cp-clone.

Bây giờ chúng ta phải nhìn vào các tùy chọn này để xem ai trong số họ có thể làm những gì bạn muốn:

-funswitch-loops
Move chi nhánh với vòng lặp điều kiện bất biến ra khỏi vòng lặp, với các bản sao của vòng lặp trên cả hai nhánh (được sửa đổi theo kết quả của điều kiện).

Thì đấy! Với -O3 bạn sẽ nhận được tối ưu hóa bạn muốn.

+0

+1 để được giải thích và tham khảo các trang của người đàn ông. Nhưng tôi muốn nói thêm rằng nếu tất cả các OP thực sự muốn là unswitch-loops, họ chỉ có thể sử dụng -funswitch-loop mà không -O3. – user2752635

2

Vâng, điều đó phụ thuộc vào nhiều thứ.

Kể từ khi, bạn đang sử dụng gcc, bạn luôn có thể kiểm tra xem nó đã làm cho một chương trình cụ thể bằng cách gọi gcc -o -S fileName.c

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