Điều gì là quan trọng khi tối ưu hóa cho bộ đệm CPU (bằng C)?


13

Đọc những hai câu hỏi , tôi thấy rằng sự hiểu biết hành vi bộ nhớ đệm CPU có thể quan trọng khi giao dịch với khối lượng lớn dữ liệu trong bộ nhớ. Tôi muốn hiểu cách thức hoạt động của bộ nhớ đệm để thêm một công cụ khác vào hộp công cụ tối ưu hóa của tôi.

Các điểm cốt lõi về cách thức hoạt động của bộ đệm CPU để tôi có thể viết mã sử dụng hợp lý? Liên quan, có cách nào để mã hồ sơ để xem nếu sử dụng bộ đệm kém làm chậm mọi thứ?


Bộ nhớ cache không giống nhau ở mọi nơi; rõ ràng nhất, chúng khác nhau về kích thước. Đừng mong đợi tìm hiểu bất kỳ bí mật sâu sắc nào, chỉ những thực hành tốt (như lời khuyên của Michael Borgwardt).
David Thornley

Câu trả lời:


17
  • Giữ dữ liệu của bạn nhỏ nếu có thể
  • Giữ những thứ sẽ được truy cập cùng nhau (hoặc ngay sau cái khác) cạnh nhau trong bộ nhớ
  • Tìm hiểu về các tham số tối ưu hóa của trình biên dịch của bạn
  • Đọc những gì mọi lập trình viên nên biết về bộ nhớ để biết thêm chi tiết hơn bạn có thể muốn

+1 cho nhóm Giữ những thứ sẽ được truy cập cùng nhau bên cạnh nhau; đó là một điều dễ quên.
Donal Fellows

Và nói với trình biên dịch để tối ưu hóa.
đúng

@WTP: phải - đã thêm.
Michael Borgwardt

Ngoài ra, giữ cho mutexes tách biệt tốt. Thay đổi một mutex (nên) xóa tất cả các dòng bộ đệm trong đó, trên tất cả các CPU. Đây có thể là một thành công lớn nếu bạn quản lý để có được 2-3 mutexes trong một dòng bộ đệm.
Vatine

12

Sự phức tạp của vấn đề này đã vượt quá tầm hiểu biết của con người ngày nay. (Đã như vậy từ 5 năm trước.) Kết hợp điều đó với song song vectơ ngắn (SIMD) và bạn có cảm giác vô vọng rằng việc tối ưu hóa mã bằng tay không còn khả thi về mặt kinh tế - không phải là không thể, nhưng nó sẽ không thể không được hiệu quả chi phí nữa.

Cách tiếp cận hiện tại là dựa vào việc dạy máy tính cách tối ưu hóa - bằng cách thực hiện các biến thể mã tính toán cùng một câu trả lời với các cấu trúc khác nhau (vòng lặp, cấu trúc dữ liệu, thuật toán) và tự động đánh giá hiệu suất. Các quy tắc cho chuyển đổi mã được chỉ định với một mô hình toán học rất nghiêm ngặt, vì vậy đó là điều mà cả các nhà khoa học máy tính có thể hiểu và máy tính có thể thực thi.

Sau đây là một liên kết được đăng bởi Larry OBrien trong một trong những câu trả lời của ông .

http://onward-conference.org/2011/images/Pueschel_2011_AutomaticPerformanceProgramming_Onward11.pdf


2
triển khai BLAS fasttest (GotoBLAS) sử dụng mã được tối ưu hóa bằng tay để đảm bảo sử dụng bộ đệm tối đa cho phép nhân ma trận
quant_dev

2

Hoàn toàn có thể hiểu và tối ưu hóa cho bộ nhớ cache. Nó bắt đầu với sự hiểu biết về phần cứng và tiếp tục với việc kiểm soát hệ thống. Bạn càng ít kiểm soát hệ thống, bạn càng ít có khả năng thành công. Linux hoặc Windows chạy một loạt các ứng dụng / luồng không chạy.

Hầu hết các bộ nhớ cache có phần giống nhau trong các thuộc tính của chúng, sử dụng một phần của trường địa chỉ để tìm kiếm các lần truy cập, có độ sâu (cách) và chiều rộng (dòng bộ đệm). Một số có bộ đệm ghi, một số có thể được cấu hình để ghi qua hoặc bỏ qua bộ đệm khi ghi, v.v.

Bạn cần nhận thức sâu sắc về tất cả các giao dịch bộ nhớ đang diễn ra đang lưu vào bộ đệm đó (một số hệ thống có hướng dẫn độc lập và bộ đệm dữ liệu giúp cho công việc dễ dàng hơn).

Bạn có thể dễ dàng tạo bộ đệm vô dụng bằng cách không quản lý cẩn thận bộ nhớ của mình. Ví dụ: nếu bạn có nhiều khối dữ liệu bạn đang xử lý, hy vọng giữ chúng trong bộ nhớ cache, nhưng chúng có trong bộ nhớ tại các địa chỉ thậm chí là bội số so với kiểm tra lần truy cập / lỗi của bộ nhớ cache, giả sử 0x10000 0x20000 0x30000 và bạn có nhiều hơn những cách này trong bộ đệm, bạn có thể sẽ nhanh chóng tạo ra thứ gì đó chạy khá chậm khi bật bộ đệm, chậm hơn so với khi tắt bộ đệm. Nhưng thay đổi điều đó thành có lẽ 0x10000, 0x21000, 0x32000 và điều đó có thể đủ để tận dụng tối đa bộ nhớ cache, giảm các vụ trục xuất.

Điểm mấu chốt, chìa khóa để tối ưu hóa cho bộ đệm (tốt, ngoài việc hiểu rõ về hệ thống) là giữ tất cả những thứ bạn cần hiệu năng trong bộ đệm cùng một lúc, tổ chức dữ liệu đó sao cho có thể có tất cả trong bộ nhớ cache cùng một lúc. Và ngăn chặn những thứ như thực thi mã, gián đoạn và các sự kiện thông thường hoặc ngẫu nhiên khác để loại bỏ các phần quan trọng của dữ liệu này bạn đang sử dụng.

Mã cũng vậy. Mặc dù khó hơn một chút vì bạn cần kiểm soát các vị trí nơi mã sống để tránh va chạm với mã khác mà bạn muốn giữ trong bộ đệm. Trong khi kiểm tra / lược tả bất kỳ mã nào đi qua bộ đệm có thêm một dòng mã ở đây và thậm chí một nop, bất cứ điều gì thay đổi hoặc thay đổi địa chỉ nơi mã nằm từ biên dịch này sang mã khác cho cùng một mã, sẽ thay đổi trong đó các dòng bộ đệm nằm trong mã đó và thay đổi những gì bị đuổi và những gì không cho các phần quan trọng.


1

Cả hai câu trả lời của nwongMichael Borgwardt đều đưa ra lời khuyên tốt.

Ngoài ra, trước tiên hãy tin tưởng tối ưu hóa của nhà soạn nhạc về các vấn đề này.

Nếu sử dụng trình biên dịch GCC gần đây, bạn có thể sử dụng (với phân tích cú pháp) __builtin_prefetchchức năng của nó . Xem câu trả lời này trên stackoverflow.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.