c++ - Is it preferred to access the first dimension first than to access the second dimension of a 2 dimension array? -


यहाँ कोड है,

  int array [x] [y] = {0 ,}; 1 के लिए (int x = 0; x & lt; X; x ++) के लिए डेटा का उपयोग करने के लिए 1 रास्ता (int y = 0; y & lt; Y; y ++) सरणी [x] [y] = गणना (); // के लिए डेटा (एट y = 0; y & lt; Y; y ++) के लिए (int x = 0; x & lt; X; x ++) सरणी [x] [y] = गणना के लिए डेटा का उपयोग करने का दूसरा तरीका;  

क्या यह सच है कि पहला तरीका सीपीयू कैश (एल 1, एल 2?) अनुकूलन के बाद से दूसरे से ज्यादा कुशल है? दूसरे शब्दों में, क्या अनुक्रमिक एक्सेस पैटर्न को रैम के लिए भी पसंद किया जाता है?

आप इसे बेहतर समझेंगे आप स्मृति में अपनी सरणी की एक तस्वीर खींचना:

  वाई - & gt; एक्स XXXXX ... | XXXXX v xxxxx ।  

आप पहुंचने वाले पते वाई दिशा (345, 345 + 1, 345 + 2 ...) में रैखिक बढ़ेंगे, लेकिन वाई के बड़े होने पर एक्स दिशा में बेतहाशा कूदता है (345, 345 + एक्स, 345 + X * 2)। कैश लोड स्मृति के ब्लॉक के रूप में, आप बहुत बड़ी वाई के साथ जल्द ही उनमें से कूद लेंगे, लेकिन कैश को ताज़ा करने के लिए जब तक वाई दिशा में चलते समय हमेशा कैश पृष्ठ में रहेगा।

यह भी ध्यान रखें कि गतिशील आवंटन का उपयोग करते समय यह प्रभाव अधिक चरम हो सकता है। पूर्ण अनुकूलन वाला निम्न प्रोग्राम का उपयोग करने से मुझे निम्नलिखित आउटपुट (सेकंड में सेकंड्स) देता है

  0.615000 9.878000  

संपादित करें: अन्य रोचक उपायों:

सरणी कोड को int सरणी के साथ बदलकर [एक्स] [वाई]; स्टैक मेमोरी का उपयोग करेगा जो सीमित है, इसलिए आप बहुत अधिक एक्स / वाई मानों का परीक्षण नहीं कर सकते हैं, लेकिन यह भी तेज़:

  0.000000 0.000000  

int सरणी का उपयोग करना [एक्स] [वाई]; एक वैश्विक चर के रूप में ढेर के एक ब्लॉक का उपयोग करेगा स्मृति और फिर धीमी है। इसलिए भी गतिशील आवंटन के बिना, पहला मामला बहुत बेहतर होता है:

  0.929000 8.944000  

एक्स = 1500, वाई = 1500 से पता चलता है कि प्रभाव छोटे एरे के साथ भी मापने योग्य है:

  0.008000 0.059000  

EDIT2: यह भी ध्यान रखें कि कोड के अन्य संभव अनुकूलन हैं जैसा कि आल्फ़ ने कहा आपके प्रश्न पर टिप्पणी में इस ऑप्टिमाइज़ेशन का उपयोग वास्तव में गति को लगभग दुगुना (एक्स = वाई = 10000 के लिए 0.453 सेकंड):

  // (int x = 0; x & lt; X) के लिए सरणी का उपयोग करने का एक भी तेज़ तरीका ; X ++) {int * arrayptr = array [x]; के लिए (int y = 0; y & lt; Y; y ++, arrayptr ++) * arrayptr = x; }  

संहिता: (ध्यान दें कि आप इसका उपयोग अपने मामले को मापने के लिए भी कर सकते हैं जहां अंतर बड़ा एक्स और वाई को छोड़कर चरम नहीं होना चाहिए। दूसरों की तरह पहले से ही कहा गया है, यह मापें और आप 'प्रबुद्ध हो जाएगा)।

  #include & lt; stdio.h & gt; # शामिल करें & lt; stdlib.h & gt; # शामिल करें & lt; time.h & gt; #define X 10000 # परिभाषित वाई 10000 int main () {int ** array = new int * [X]; के लिए (int x = 0; x & lt; X; x ++) {सरणी [x] = नया इंट [वाई]; } डबल सी = घड़ी (); // (एट y = 0; y & lt; Y; y ++) सरणी [x] [y] = x के लिए (int x = 0; x & lt; X; x ++) के लिए डेटा तक पहुंचने के लिए 1 रास्ता; Printf ("% f \ n", (घड़ी () - c) / CLOCKS_PER_SEC); सी = घड़ी (); // के लिए डेटा (एट y = 0; y & lt; Y; y ++) के लिए (int x = 0; x & lt; X; x ++) सरणी [x] [y] = x के लिए एक्सेस करने का दूसरा तरीका; Printf ("% f \ n", (घड़ी () - c) / CLOCKS_PER_SEC); के लिए (int x = 0; x & lt; X; x ++) {हटाएं (सरणी [x]); } हटाएं (सरणी); }  

Comments