2009-12-17 34 views
53

có cách nào trong C++ để xác định kích thước bộ nhớ cache của CPU không? tôi có một thuật toán xử lý rất nhiều dữ liệu và tôi muốn chia nhỏ dữ liệu này thành các phần sao cho chúng phù hợp với bộ nhớ cache. Điều này có thể không? Bạn có thể cho tôi bất kỳ gợi ý nào khác về lập trình với kích thước bộ nhớ cache trong tâm trí (đặc biệt là đối với xử lý dữ liệu đa luồng/đa lõi) không?Lập trình nhận biết bộ nhớ cache C++

Cảm ơn!

+0

Thử nghiệm của tôi với các thuật toán bị chặn cho thấy rằng nó can thiệp vào tối ưu hóa GCC. Kích thước khối tối ưu không phải lúc nào cũng là kích thước bộ nhớ cache l1. Tôi đề xuất thực hiện các thử nghiệm với các kích thước khối khác nhau. –

Trả lời

4

đọc cpuid của cpu (x86) và sau đó xác định kích thước bộ nhớ cache bằng bảng tra cứu. Bảng phải được lấp đầy với các kích thước bộ nhớ cache mà nhà sản xuất của cpu xuất bản trong các hướng dẫn lập trình của nó.

+2

hey có vẻ thú vị! có bất kỳ bảng được chuẩn bị sẵn có trực tuyến nào không? – Mat

+0

http://www.x86-guide.com/en/index.html Có thể có các bảng như vậy. Tuy nhiên, vấn đề với điều này là bạn làm gì với một cpu không xác định và bạn có muốn cập nhật chương trình mỗi lần một cpu mới xuất hiện không? –

+1

Giải pháp này có bị hỏng không nếu chương trình của bạn được sử dụng trên CPU được phát hành sau khi chương trình của bạn được phát hành? –

11

C++ chính nó không "quan tâm" về bộ đệm CPU, do đó không hỗ trợ truy vấn kích thước bộ nhớ cache được tích hợp sẵn trong ngôn ngữ. Nếu bạn đang phát triển cho Windows, thì có GetLogicalProcessorInformation()-function, có thể được sử dụng để truy vấn thông tin về bộ đệm CPU.

+0

? Tất nhiên C++ quan tâm đến cache CPU. Không quan tâm về điều đó có nghĩa là sẽ chậm hơn 100-1000 lần so với khi bạn đang ở trong những con đường nóng. Và không có hỗ trợ cho điều đó được xây dựng trong ngôn ngữ bởi vì số một không phải tất cả các hệ thống hỗ trợ nó và số hai biết kích thước bộ nhớ cache là chủ yếu là hoàn toàn không liên quan mà không có toàn quyền kiểm soát các chiến lược phân bổ bộ nhớ. C++ cung cấp cho bạn rất nhiều nhưng không đủ để chơi "cache daddy" – thesaint

+0

Nếu có, trình biên dịch C/C++ ** của bạn ** quan tâm đến bộ nhớ đệm.Bạn có thể sử dụng cờ '-march' trên GCC để cho phép nó tối ưu hóa cho một số CPU cụ thể. Ngoài ra còn có: http://en.cppreference.com/w/cpp/atomic/memory_order – snowflake

4

Tùy thuộc vào những gì bạn đang cố gắng làm, bạn cũng có thể để nó ở một số thư viện. Vì bạn đề cập đến xử lý đa lõi, bạn có thể muốn xem Intel Threading Building Blocks.

TBB bao gồm các bộ cấp phát bộ nhớ nhận biết bộ nhớ cache. Cụ thể hơn, hãy kiểm tra cache_aligned_allocator (trong tài liệu tham chiếu, tôi không thể tìm thấy bất kỳ liên kết trực tiếp nào).

-1

Bộ nhớ cache thường sẽ làm điều đúng. Nỗi lo thực sự duy nhất cho lập trình viên bình thường là chia sẻ sai, và bạn không thể quan tâm đến điều đó khi chạy vì nó yêu cầu chỉ thị của trình biên dịch.

+2

Không giải quyết được câu hỏi. – JBentley

15

Theo "What every programmer should know about memory", bởi Ulrich Drepper bạn có thể làm như sau trên Linux:

Một khi chúng ta có một công thức cho bộ nhớ yêu cầu chúng ta có thể so sánh nó với kích thước cache. Như đã đề cập trước đây, bộ nhớ cache có thể được chia sẻ với nhiều nhân các lõi khác. Hiện tại, {There chắc chắn sẽ sớm là cách tốt nhất!} Cách duy nhất để có được thông tin chính xác mà không cần mã hóa kiến ​​thức là thông qua hệ thống tập tin/sys . Trong Bảng 5.2, chúng ta đã thấy những gì hạt nhân xuất bản khoảng phần cứng. Một chương trình có để tìm thư mục:

/sys/devices/system/cpu/cpu*/cache 

này được liệt kê trong Section 6: What Programmers Can Do.

Ông cũng mô tả một thử nghiệm ngắn ngay bên dưới Hình 6.5 có thể được sử dụng để xác định kích thước bộ nhớ cache L1D nếu bạn không thể lấy nó từ hệ điều hành.

Có một điều nữa tôi gặp trong bài báo của anh ấy: sysconf(_SC_LEVEL2_CACHE_SIZE) là một cuộc gọi hệ thống trên Linux được cho là sẽ trả về kích thước bộ nhớ cache L2 mặc dù nó dường như không được ghi lại rõ ràng.

8

Preallocate một mảng lớn. Sau đó truy cập từng phần tử tuần tự và ghi lại thời gian cho mỗi lần truy cập. Lý tưởng nhất là sẽ có một bước nhảy trong thời gian truy cập khi nhớ cache xảy ra. Sau đó, bạn có thể tính toán Cache L1 của bạn. Nó có thể không hoạt động nhưng đáng thử.

4

Thú vị đủ, tôi đã viết một chương trình để làm điều này một thời gian trước (trong C mặc dù, nhưng tôi chắc chắn nó sẽ được dễ dàng để kết hợp trong mã C + +).

http://github.com/wowus/CacheLineDetection/blob/master/Cache%20Line%20Detection/cache.c

Chức năng get_cache_line là một trong những thú vị, mà trả về vị trí của ngay trước khi các cành lớn nhất trong thời gian dữ liệu của mảng truy cập. Nó đoán chính xác trên máy của tôi! Nếu bất cứ điều gì khác, nó có thể giúp bạn thực hiện của riêng bạn.

Nó dựa tắt của bài viết này, mà ban đầu được khơi gợi sự quan tâm của tôi: http://igoro.com/archive/gallery-of-processor-cache-effects/

4

Bạn có thể thấy chủ đề này: http://software.intel.com/en-us/forums/topic/296674

Câu trả lời ngắn gọn là trong chủ đề khác này:

On hiện đại Phần cứng IA-32, kích thước đường bộ nhớ cache là 64. Giá trị 128 là một di sản của Kiến trúc Intel Netburst (ví dụ Intel Pentium D) trong đó các dòng 64 byte được ghép nối thành các sector 128 byte. Khi một dòng trong một sector được tìm nạp, phần cứng sẽ tự động tìm nạp dòng khác trong lĩnh vực này. Vì vậy, từ góc độ chia sẻ sai, kích thước đường dây hiệu quả là là 128 byte trên bộ vi xử lý Netburst. (http://software.intel.com/en-us/forums/topic/292721)

1

IIRC, GCC có một gợi ý __builtin_prefetch.

http://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Other-Builtins.html

có phần tuyệt vời về điều này. Về cơ bản, nó cho thấy:

__builtin_prefetch (&array[i + LookAhead], rw, locality); 

nơi rw là 0 (chuẩn bị cho đọc) hoặc 1 (chuẩn bị cho một ghi) giá trị, và địa phương sử dụng số 0-3, nơi không có địa phương và 3 là địa phương rất mạnh.

Cả hai đều là tùy chọn. LookAhead sẽ là số yếu tố cần xem xét. Nếu truy cập bộ nhớ là 100 chu kỳ, và các vòng chưa được kiểm định là hai chu kỳ, LookAhead có thể được đặt thành 50 hoặc 51.

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