उत्तर बहुत आसान है: कंपाइलर आपके असाइनमेंट को अनुकूलित करता है। यहाँ कैसे disassembly के अपने कोड के लिए की तरह लग रहा है:
10 int main() {
0x00000000004004d6 <+0>: mov $0x2710,%edx
0x00000000004004db <+5>: jmp 0x4004e7 <main+17>
15 for(int j = 0; j < N; j++){
0x00000000004004dd <+7>: sub $0x1,%eax
0x00000000004004e0 <+10>: jne 0x4004dd <main+7>
14 for(int i = 0; i < N; i++) {
0x00000000004004e2 <+12>: sub $0x1,%edx
0x00000000004004e5 <+15>: je 0x4004ee <main+24>
10 int main() {
0x00000000004004e7 <+17>: mov $0x2710,%eax
0x00000000004004ec <+22>: jmp 0x4004dd <main+7>
16 arr[i * N + j] = 10.0;
17 }
18 }
19 return 0;
20 }
0x00000000004004ee <+24>: mov $0x0,%eax
0x00000000004004f3 <+29>: retq
आप कोई कोडांतरक लाइन arr[i * N + j] = 10.0;
के लिए उत्पन्न निर्देश देखते हैं देख सकते हैं, इसलिए उन कैश आप का पालन पर्फ़ साथ कोई संबंध नहीं हैं याद करते हैं।
फिक्स काफी आसान है। सीधे शब्दों में सूचक घोषणा करने के लिए volatile
जोड़ने के लिए, अब कार्य उत्पन्न करने के लिए मजबूर कर रहा संकलक, यानी .:
volatile double *arr = malloc(sizeof(double) * N * N);
disassembly:
10 int main() {
0x0000000000400526 <+0>: sub $0x8,%rsp
11 int N = 10000;
12 volatile double *arr = malloc(sizeof(double) * N * N);
0x000000000040052a <+4>: mov $0x2faf0800,%edi
0x000000000040052f <+9>: callq 0x400410 <[email protected]>
0x0000000000400534 <+14>: mov $0x0,%edx
16 arr[i * N + j] = 10.0;
0x0000000000400539 <+19>: movsd 0xc7(%rip),%xmm0 # 0x400608
0x0000000000400541 <+27>: jmp 0x40055f <main+57>
0x0000000000400543 <+29>: movslq %edx,%rcx
0x0000000000400546 <+32>: lea (%rax,%rcx,8),%rcx
0x000000000040054a <+36>: movsd %xmm0,(%rcx)
0x000000000040054e <+40>: add $0x1,%edx
15 for(int j = 0; j < N; j++){
0x0000000000400551 <+43>: cmp %esi,%edx
0x0000000000400553 <+45>: jne 0x400543 <main+29>
0x0000000000400555 <+47>: mov %esi,%edx
14 for(int i = 0; i < N; i++) {
0x0000000000400557 <+49>: cmp $0x5f5e100,%esi
0x000000000040055d <+55>: je 0x400567 <main+65>
0x000000000040055f <+57>: lea 0x2710(%rdx),%esi
0x0000000000400565 <+63>: jmp 0x400543 <main+29>
17 }
18 }
19 return 0;
20 }
0x0000000000400567 <+65>: mov $0x0,%eax
0x000000000040056c <+70>: add $0x8,%rsp
0x0000000000400570 <+74>: retq
और भी बहुत कुछ कैश के रूप में अच्छी तरह से याद करते हैं देखते हैं।
आपके परीक्षण को चलाने से आपको बहुत शोर परिणाम मिल सकते हैं। आपको अपना माप कुछ बार चलाना चाहिए और एक औसत लेना चाहिए। Google बेंचमार्क जैसे बेंचमार्क फ्रेमवर्क हैं, इसलिए कृपया एक नज़र डालें।
और अंतिम वाला। i * N + j
और j * N + i
जैसे आपके दोनों पैटर्न, सीपीयू प्रीफेचर द्वारा आसानी से पहचानने योग्य हैं, इसलिए दोनों मामलों में कैश मिस अनुपात काफी समान होना चाहिए ...
आपके पास कौन सी सीपीयू है? 'बिल्ली/proc/cpuinfo' आपको कैश की जानकारी भी बताएगा। –
@ जोनाथन रेनहार्ट यह एक इंटेल (आर) ज़ीऑन (आर) सीपीयू है और कैश आकार 12288 केबी है। – DzedCPT
क्या आपने ऑप्टिमाइज़ेशन सक्षम प्रोग्राम को सक्षम किया था? – Lundin