2011-12-10 29 views
10

Tôi đang cố gắng để tối ưu hóa một số ++ mã RK4 GCC C bằng cách sử dụng__builtin_prefetch, Số tiền đọc được bao nhiêu?

__builtin_prefetch 

Tôi đang gặp một số rắc rối cố gắng tìm ra cách để prefetch cả lớp. Tôi không hiểu số lượng của const void *addr được đọc. Vì vậy, tôi có các giá trị tiếp theo là fromto được tải.

for (int i = from; i < to; i++) 
{ 
    double kv = myLinks[i].kv; 
    particle* from = con[i].Pfrom; 
    particle* to = con[i].Pto; 
    //Prefetch values at con[i++].Pfrom & con[i].Pto; 
    double pos = to->px- from->px; 
    double delta = from->r + to->r - pos; 
    double k1 = axcel(kv, delta, from->mass) * dt; //axcel is an inlined function 
    double k2 = axcel(kv, delta + 0.5 * k1, from->mass) * dt; 
    double k3 = axcel(kv, delta + 0.5 * k2, from->mass) * dt; 
    double k4 = axcel(kv, delta + k3, from->mass) * dt; 
    #define likely(x)  __builtin_expect((x),1) 
    if (likely(!from->bc)) 
    { 
      from->x += ((k1 + 2 * k2 + 2 * k3 + k4)/6); 
    } 
} 

Link: http://www.ibm.com/developerworks/linux/library/l-gcc-hacks/

+0

Tôi không nghĩ có nhiều điểm trong việc tối ưu hóa vi mô như vậy, ngoài mục đích học tập. CPus hiện đại là rất tốt tại prefetching của mình. – ronag

+1

Có lẽ, nhưng tôi có 1 chức năng gọi là gần 1 tỷ lần. – Mikhail

Trả lời

15

Tôi nghĩ rằng nó chỉ phát ra một FETCH hướng dẫn máy, mà về cơ bản lấy một bộ nhớ cache dòng, có kích thước là bộ xử lý cụ thể.

Ví dụ: bạn có thể sử dụng __builtin_prefetch (con[i+3].Pfrom). Bằng kinh nghiệm (nhỏ) của tôi, trong vòng lặp như vậy, tốt hơn là nên tìm nạp trước một số yếu tố trước.

Không sử dụng __builtin_prefetch quá thường xuyên (tức là không đặt quá nhiều trong vòng lặp). Đo lường hiệu suất đạt được nếu bạn cần chúng, và sử dụng tối ưu hóa GCC (ít nhất là -O2). Nếu bạn đang rất may mắn, hướng dẫn sử dụng __builtin_prefetch có thể làm tăng hiệu suất của vòng lặp của bạn bằng 10 hoặc 20% (nhưng nó cũng có thể làm tổn thương nó).

Nếu vòng lặp đó rất quan trọng đối với bạn, bạn có thể xem xét chạy trên GPU với OpenCL hoặc CUDA (nhưng yêu cầu phải mã hóa một số thường trình bằng ngôn ngữ OpenCL hoặc CUDA và điều chỉnh chúng theo phần cứng cụ thể của bạn).

Sử dụng trình biên dịch GCC gần đây (bản phát hành mới nhất là 4.6.2) bởi vì nó đang thực hiện rất nhiều tiến bộ trên các khu vực này.


(bổ sung trong tháng 1 năm 2018 :)

Cả phần cứng (bộ vi xử lý) và trình biên dịch đã thực hiện rất nhiều tiến bộ về lưu trữ, vì vậy nó có vẻ rằng việc sử dụng __builtin_prefetch là ít hữu ích ngày hôm nay (năm 2018) . Hãy chắc chắn để benchmarck.

+6

Có: nếu bạn định thực hiện điều này, hãy đảm bảo bạn đã chuẩn bị vòng lặp của mình trước và sau. Có một cơ hội bạn có thể làm cho nó tồi tệ hơn hoặc không có sự khác biệt. – 111111

+4

Cảm ơn bài đăng của bạn. Tôi đã làm 3 điểm chuẩn: không tối ưu hóa = 100%, đọc trước [i + 3] 100% và với [i + 10] 200% +. Tất cả được thực hiện với -03 và toán nhanh – Mikhail

+0

Có một số cờ tối ưu hóa ngoài '-O3' trong GCC ... –

9

Nó đọc một dòng bộ nhớ cache. Kích thước dòng bộ nhớ cache có thể thay đổi, nhưng rất có thể là 64 byte trên các CPU hiện đại. Nếu bạn cần đọc nhiều dòng bộ nhớ cache, hãy xem prefetch_range.

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