Bunun muhtemelen L2 önbelleğinizdeki çakışmalarla ilgisi vardır.
Matice1'deki önbellek eksiklikleri sorun değildir çünkü bunlara sırayla erişilir. Bununla birlikte, matice2 için tam bir sütun L2'ye uyuyorsa (yani matice2 [0, 0], matice2 [1, 0], matice2 [2, 0] ... vb'ye eriştiğinizde, hiçbir sorun çıkarılmaz) önbellek matice2 ile de özlüyor.
Şimdi, değişkeninizin bayt adresi X ise, önbelleklerin nasıl çalıştığına dair daha derine inmek için, önbellek satırından (X >> 6) ve (L - 1) olacaktır. Burada L, önbelleğinizdeki toplam önbellek satırı sayısıdır. L, her zaman 2'nin gücüdür. Altı, 2 ^ 6 == 64 bayt önbellek satırının standart boyutunda olduğu gerçeğinden gelir.
Şimdi bu ne anlama geliyor? Bu, eğer X adresime ve Y adresine sahipsem ve (X >> 6) - (Y >> 6) L ile bölünebiliyorsa (yani 2'nin büyük bir kuvveti), aynı önbellekte saklanacakları anlamına gelir.
Şimdi sorununuza geri dönersek, 2048 ile 2049 arasındaki fark nedir?
2048 bedeniniz olduğunda:
& matice2 [x, k] ve & matice2 [y, k] alırsanız, fark (& matice2 [x, k] >> 6) - (& matice2 [y, k] >> 6) 2048 * 4'e bölünebilir (boyut şamandıra). Yani 2'nin büyük bir gücü.
Bu nedenle, L2'nizin boyutuna bağlı olarak, çok sayıda önbellek satırı çakışması yaşarsınız ve bir sütunu depolamak için L2'nizin yalnızca küçük bir bölümünü kullanırsınız, böylece önbelleğinizde tam sütun depolayamazsınız, bu nedenle kötü performans elde edersiniz. .
Boyut 2049 olduğunda, fark 2049 * 4'tür ki bu 2'nin gücü değildir, bu nedenle daha az çatışmaya sahip olacaksınız ve sütununuz önbelleğinize güvenli bir şekilde sığacaktır.
Şimdi bu teoriyi test etmek için yapabileceğiniz birkaç şey var:
Dizi matice2 dizinizi bu matice2 [razmor, 4096] gibi ayırın ve razmor = 1024, 1025 veya herhangi bir boyutta çalıştırın ve daha önce sahip olduklarınıza kıyasla çok kötü performans görmelisiniz. Bunun nedeni, tüm sütunları birbiriyle çakışacak şekilde zorla hizalamanızdır.
Sonra matice2'yi [razmor, 4097] deneyin ve herhangi bir boyutta çalıştırın ve çok daha iyi performans görmelisiniz.