Điều này có thể có liên quan đến xung đột trong bộ đệm L2 của bạn.
Lỗi bộ nhớ cache trên matice1 không phải là vấn đề vì chúng được truy cập tuần tự. Tuy nhiên, đối với matice2 nếu một cột đầy đủ phù hợp với L2 (nghĩa là khi bạn truy cập matice2 [0, 0], matice2 [1, 0], matice2 [2, 0] ... vv, không có gì bị đuổi) nhớ cache với matice2.
Bây giờ để đi sâu hơn về cách thức hoạt động của bộ nhớ cache, nếu địa chỉ byte của biến của bạn là X, hơn dòng bộ đệm cho nó sẽ là (X >> 6) & (L - 1). Trong đó L là tổng số dòng bộ đệm trong bộ đệm của bạn. L luôn có sức mạnh bằng 2. Sáu xuất phát từ thực tế rằng 2 ^ 6 == 64 byte là kích thước chuẩn của dòng bộ đệm.
Bây giờ điều này có nghĩa là gì? Chà, điều đó có nghĩa là nếu tôi có địa chỉ X và địa chỉ Y và (X >> 6) - (Y >> 6) chia hết cho L (tức là một số công suất lớn bằng 2), chúng sẽ được lưu trong cùng một dòng.
Bây giờ để trở lại vấn đề của bạn, sự khác biệt giữa năm 2048 và 2049 là gì,
khi 2048 là kích thước của bạn:
nếu bạn lấy & matice2 [x, k] và & matice2 [y, k] thì sự khác biệt (& matice2 [x, k] >> 6) - (& matice2 [y, k] >> 6) sẽ chia hết cho 2048 * 4 (kích thước của phao). Vì vậy, một sức mạnh lớn của 2.
Do đó, tùy thuộc vào kích thước L2 của bạn, bạn sẽ có rất nhiều xung đột dòng bộ đệm và chỉ sử dụng một phần nhỏ L2 để lưu trữ một cột, do đó bạn thực sự không thể lưu trữ cột đầy đủ trong bộ đệm của mình, do đó bạn sẽ có hiệu suất kém .
Khi kích thước là 2049, thì sự khác biệt là 2049 * 4 không phải là sức mạnh của 2 do đó bạn sẽ có ít xung đột hơn và cột của bạn sẽ phù hợp với bộ đệm của bạn một cách an toàn.
Bây giờ để kiểm tra lý thuyết này, có một số điều bạn có thể làm:
Phân bổ mảng matice2 của bạn như matice2 [razmor, 4096] và chạy với razmor = 1024, 1025 hoặc bất kỳ kích thước nào, và bạn sẽ thấy hiệu suất rất kém so với những gì bạn đã có trước đây. Điều này là do bạn mạnh mẽ sắp xếp tất cả các cột để xung đột với nhau.
Sau đó thử matice2 [razmor, 4097] và chạy nó với bất kỳ kích thước nào và bạn sẽ thấy hiệu suất tốt hơn nhiều.