Tôi cần tính toán mảng (writeArray) sử dụng mảng khác (readArray) nhưng vấn đề là ánh xạ chỉ mục không giống nhau giữa các mảng (Giá trị tại chỉ số x của writeArray phải được tính với giá trị tại chỉ mục y của readArray). không phải là rất thân thiện với bộ nhớ cache.Tại sao bộ nhớ cache đọc bỏ lỡ nhanh hơn ghi lỗi?
Tuy nhiên tôi có thể chọn xem vòng lặp duyệt readArray tuần tự hay writeArray tuần tự.
Vì vậy, đây là một mã đơn giản:
int *readArray = new int[ARRAY_SIZE]; // Array to read
int *writeArray = new int[ARRAY_SIZE]; // Array to write
int *refArray = new int[ARRAY_SIZE]; // Index mapping between read and write, could be also array of pointers instead indexes
// Code not showed here : Initialization of readArray with values, writeArray with zeroes and refArray with random indexes for mapping between readArray and writeArray (values of indexes between 0 and ARRAY_SIZE - 1)
// Version 1: Random read (browse writeArray/refArray sequentially)
for (int n = 0; n < ARRAY_SIZE; ++n) {
writeArray[n] = readArray[refArray[n]];
}
// Version 2: Random write (browse readArray/refArray sequentially)
for (int n = 0; n < ARRAY_SIZE; ++n) {
writeArray[refArray[n]] = readArray[n];
}
Tôi đã suy nghĩ bộ nhớ cache mà đọc bỏ lỡ là chậm hơn viết bỏ lỡ (vì CPU cần phải chờ đợi trước khi đọc trọn vẹn nếu chỉ lệnh kế tiếp phụ thuộc dữ liệu đọc nhưng đối với viết nó không cần phải đợi để xử lý lệnh tiếp theo) nhưng với lược tả có vẻ như phiên bản 1 nhanh hơn phiên bản 2 (phiên bản 2 chậm hơn khoảng 50% so với phiên bản 1).
Tôi cũng đã cố gắng này:
// Version 3: Same as version 2 but without polluting cache
for (int n = 0; n < ARRAY_SIZE; ++n) {
_mm_stream_si32(&writeArray[refArray[n]], readArray[n]);
}
Bởi vì tôi không cần phải đọc giá trị của writeArray vì vậy không có lý do gì để làm ô nhiễm bộ nhớ cache với giá trị bằng văn bản nhưng phiên bản này là chậm hơn nhiều hơn các phiên bản khác (6700% chậm hơn phiên bản 1).
Tại sao viết thư bỏ lỡ chậm hơn đọc bỏ lỡ? Tại sao bỏ qua bộ nhớ cache để viết chậm hơn sử dụng nó ngay cả khi chúng ta không đọc những dữ liệu sau này?
Tôi không có chuyên gia trong lĩnh vực này, nhưng tôi sẽ đặt cược nó có một cái gì đó để làm với pipelining. – Barmar
Nếu máy của bạn là OOO, thì bỏ lỡ đọc không chặn các hướng dẫn khác không phụ thuộc vào dữ liệu này. Trong trường hợp này, đọc các lỗi xảy ra rất dày đặc và được phục vụ theo kiểu pipelined. Viết ghi nhớ là khác nhau, viết bỏ lỡ thường phải được phục vụ trước khi bất cứ điều gì có thể tiến hành để ngăn chặn đọc trước khi viết. – user3528438
@ user3528438 nghe có vẻ giống như một quyết định thiết kế. Việc viết phải tuôn ra tất cả các lần đọc, sau đó viết và "kết thúc". Đọc có thể đường ống. Bạn có thể đảo ngược này (đọc tuôn ra tất cả viết, và đọc ngay lập tức, viết đường ống), nhưng pipelining cả hai là khó khăn. Và có lẽ đọc là phổ biến hơn viết? Hoặc cảm thấy như nó phải nhanh hơn. – Yakk