2012-03-03 9 views
5
// if I know that in_x will never be bigger than Max 
template <unsigned Max> 
void foo(unsigned in_x) 
{ 
    unsigned cap = Max; 

    // I can tell the compiler this loop will never run more than log(Max) times 
    for (; cap != 0 && in_x != 0; cap >>= 1, in_x >>= 1) 
    { 
    } 
} 

Như đã trình bày trong đoạn mã trên, tôi đoán là nếu tôi chỉ cần viếtLàm thế nào để cung cấp cho các trình biên dịch các gợi ý về thời gian tối đa một vòng lặp sẽ chạy

for (; in_x = 0;! In_x> > = 1)

trình biên dịch sẽ không hủy vòng lặp, vì nó không thể chắc chắn về in_x tối đa có thể.

Tôi muốn biết tôi có đúng hay sai và nếu có một số cách tốt hơn để giải quyết những việc như vậy.


Hoặc có thể các vấn đề có thể được khái quát như thể người ta có thể viết một số mã để nói với trình biên dịch trong phạm vi của một số giá trị thời gian chạy, và mã như vậy không nhất thiết phải được biên dịch vào thời gian chạy nhị phân.


Quả thật, chiến đấu với các trình biên dịch XD

// with MSC 
// if no __forceinline here, unrolling is ok, but the function will not be inlined 
// if I add __forceinline here, lol, the entire loop is unrolled (or should I say the tree is expanded)... 
// compiler freezes when Max is something like 1024 
template <int Max> 
__forceinline void find(int **in_a, int in_size, int in_key) 
{ 
    if (in_size == 0) 
    { 
     return; 
    } 

    if (Max == 0) 
    { 
     return; 
    } 

    { 
     int m = in_size/2; 

     if ((*in_a)[m] >= in_key) 
     { 
      find<Max/2>(in_a, m, in_key); 
     } 
     else 
     { 
      *in_a = *in_a + m + 1; 

      find<Max - Max/2 - 1>(in_a, in_size - (m + 1), in_key); 
     } 
    } 
} 
+8

Những thứ tối ưu hóa vi mô này có xu hướng rất bị lỗi khi bạn đang chiến đấu với trình biên dịch. Tôi gần như luôn luôn kết thúc bằng tay unrolling, nhưng tôi đã không bao giờ cố gắng để ngăn chặn các trình biên dịch từ tự động unrolling. – Mysticial

+0

Thậm chí nếu một trình biên dịch biết 'Max' và tính toán' log (Max) ', giả sử rằng giá trị đó đủ lớn để unrolling là một ý tưởng tồi. Vâng, người ta có thể lập luận rằng có lẽ trình biên dịch có thể sử dụng một ngưỡng. Nhưng ngưỡng đó có thể phụ thuộc vào vòng lặp cụ thể. Dự đoán hiệu suất là một vấn đề trình biên dịch khó. – Jerry

+0

@Jerry log (Max) sẽ <= 32 (chưa ký, không lớn). –

Trả lời

3

Cách thích hợp để đạt được loại hành vi là để cuộn un vòng lặp chính mình sử dụng TMP. Ngay cả với điều này, bạn sẽ được dựa vào sự hợp tác biên dịch cho nội tuyến lớn (đó là không được cấp). Hãy xem mã sau đây để xem liệu mã đó có hữu ích không:

template <unsigned char MaxRec> 
inline void foo(unsigned in_x) 
{ 
    if (MaxRec == 0) // will be eliminated at compile time 
     return; // tells the compiler to stop the pseudo recursion 

    if (in_x == 0) { 
     // TODO : end recursion; 
     return; 
    }; 

    // TODO: Process for iteration rec 

    // Note: NOT recursion, the compiler would not be able to inline 
    foo<MaxRec-1>(in_x >> 1); 
} 

// Usage: 
foo<5>(in_x); // doubt the compiler will inline 32 times, but you can try. 
+1

MSC sẽ hủy đăng ký tìm kiếm nhị phân với độ sâu dưới 5 theo cách này, không có nội tuyến bên ngoài nhất foo mặc dù ... Nếu buộc nó sẽ inline cả nhánh thay vì bỏ vòng lặp. – BlueWanderer