मतलाब में 'छोरों' के लिए लिखने का सबसे कुशल तरीका क्या है?


12

मैंने पढ़ा है कि यदि, उदाहरण के लिए, मेरे पास एक दोहरा forलूप है जो मैट्रिक्स के अनुक्रमित पर चलता है, तो बाहरी लूप में कॉलम रनिंग इंडेक्स को अधिक कुशल बनाना है। उदाहरण के लिए:

a=zeros(1000);
for j=1:1000
 for i=1:1000
  a(i,j)=1;
 end
end

यदि मेरे पास तीन या अधिक forलूप हैं, तो इसे कोड करने का सबसे कुशल तरीका क्या है ?

उदाहरण के लिए:

a=zeros(100,100,100);
for j=1:100
 for i=1:100
  for k=1:100
   a(i,j,k)=1;
  end
 end
end

4
ForMATLAB में छोरों की गति बहुत धीमी है। आपको जब भी संभव हो MATLAB में स्पष्ट छोरों से बचना चाहिए। इसके बजाय, आमतौर पर एक समस्या मैट्रिक्स / वेक्टर संचालन के संदर्भ में व्यक्त की जा सकती है। यही MATLABic तरीका है। मैट्रिक्स को शुरू करने के लिए बहुत सारे अंतर्निहित कार्य भी हैं, उदाहरण के लिए, एक फ़ंक्शन, वाले () हैं , जो मैट्रिक्स के सभी तत्वों को 1 से (विस्तार द्वारा, किसी भी मूल्य पर गुणन द्वारा निर्धारित करेगा ) (सभी मैट्रिक्स द्वारा गुणा)))। यह 3-डी सरणियों पर भी काम करता है (जो मुझे लगता है कि यहां उदाहरण प्रस्तुत करता है)।
पीटर मोर्टेंसन

3
@PeterMortensen सी और पायथन की तुलना में मतलबी में छोरों की दक्षता किस कारक (मोटे तौर पर) से कम है? और यही वजह है कि? इसके अलावा, मतलाब में छोरों की दक्षता पिछले कई वर्षों में बेहतर नहीं हुई?
टेन्सोआरआर

3
@PeterMortensen "आम तौर पर मैट्रिक्स / वेक्टर ऑपरेशन के संदर्भ में एक समस्या व्यक्त की जा सकती है" - "आमतौर पर" के कुछ मूल्यों के लिए, हाँ। IMO यह कहना अधिक सटीक है कि मतलाब में काम करने वाले लोगों और जैसी दशकों की सभी चीजों को अनदेखा करने की संस्कृति है, जो मैट्रिक्स / वेक्टर ऑपरेशन के साथ नहीं हो सकती हैं, इतना सब कुछ उस हथौड़ा के लिए उन्हें एक नाखून की तरह दिखता है । और हमें सिर्फ यह नहीं कहना चाहिए कि "मतलाब में छोरों की गति धीमी है" लेकिन "मतलाब धीमा है" (यह केवल सी और फोरट्रान में लिखी गई ला प्राइमेटिव की एक तेज़ लाइब्रेरी से जुड़ा हुआ है)।
लेफ्टरनैबाउट

5
लूप्स के लिए प्रदर्शन विवादास्पद है: matlabtips.com/matlab-is-no-longer-slow-at-for-loops
oh Jully

@leftaroundabout सच है। एक व्याख्या (या अर्द्ध-व्याख्या की गई) भाषा में गति के बारे में चिंतित होना एक स्पष्ट संकेत है कि आपको एक XY समस्या है जहां वास्तविक समाधान "इस भाषा का उपयोग न करें" है। यदि आप सिमुलिंक में कोड जेनरेशन का उपयोग कर रहे हैं तो कोर्स का अपवाद है, लेकिन फिर सवाल यह है कि सी कोड जनरेटर क्या है और यह कितना कुशल है।
ग्राहम

जवाबों:


18

संक्षिप्त उत्तर, आप अंतरतम लूप पर सबसे बाईं ओर सूचकांक चाहते हैं। आपके उदाहरण में, लूप इंडेक्स k, j, i होगा और ऐरे इंडेक्स i, j, k होंगे। यह कैसे MATLAB स्मृति में विभिन्न आयामों को संग्रहीत करता है। अधिक के लिए, इस लाल पोस्ट के # 13 देखें ।


2
या अंतर्निहित फ़ंक्शन वाले () का उपयोग करें
पीटर मोर्टेंसन

5
@Peter ओपी का उदाहरण लगभग निश्चित रूप से लूप के लिए केवल एक खिलौना उदाहरण है जो कुछ करता है और वास्तविक उपयोग का मामला नहीं है।
मैट

@ मैट आप सही हैं।
टेन्सो

11

कुछ हद तक जवाब है कि यह बताता है कि सबसे अधिक तेजी से अलग-अलग छोड़ दिया जाने वाला सूचकांक सबसे अधिक कुशल क्यों है। दो प्रमुख बातें हैं जिन्हें आपको समझना आवश्यक है।

सबसे पहले, MATLAB (और फोरट्रान, लेकिन सी और अधिकांश अन्य प्रोग्रामिंग भाषाएं नहीं हैं) मेमोरी में सरणियों को "कॉलम प्रमुख क्रम में।" उदाहरण के लिए, यदि A 2 बाय 3 मैट्रिक्स 10 है, तो प्रविष्टियों को क्रम में मेमोरी में संग्रहीत किया जाएगा

ए (1,1,1)

ए (2,1,1)

ए (1,2,1)

ए (2,2,1)

ए (1,3,1)

ए (2,3,1)

ए (1,1,2)

ए (2,1,2)

...

ए (2,3,10)

स्तंभ प्रमुख आदेश की यह पसंद मनमानी है- हम आसानी से एक "पंक्ति प्रमुख आदेश" सम्मेलन को अपना सकते हैं, और वास्तव में यही सी और कुछ अन्य प्रोग्रामिंग भाषाओं में किया जाता है।

दूसरी महत्वपूर्ण बात जो आपको समझने की आवश्यकता है कि आधुनिक प्रोसेसर एक समय में मेमोरी को एक स्थान तक नहीं पहुंचाते हैं, बल्कि 64 या 128 सन्निकट बाइट्स (8 या 16 डबल सटीक फ़्लोटिंग पॉइंट नंबर) की "कैश लाइनों" को लोड और स्टोर करते हैं। स्मृति से एक समय में। डेटा का ये हिस्सा अस्थायी रूप से एक तेज़ मेमोरी कैश में संग्रहीत किया जाता है और आवश्यकतानुसार वापस लिखा जाता है। (व्यवहार में कैश आर्किटेक्चर अब कैश मेमोरी के 3 या 4 स्तरों के साथ काफी जटिल है, लेकिन मूल विचार को उस प्रकार के एक-स्तरीय कैश के साथ समझाया जा सकता है जो कंप्यूटर ने मेरे छोटे दिनों में किया था।)

A

यदि लूप को नेस्ट किया जाता है ताकि अंतरतम लूप पंक्ति सबस्क्रिप्ट को अपडेट करता है, तो सरणी प्रविष्टियों को क्रम ए (1,1), ए (2,1), ए (3,1), ... में एक्सेस किया जाएगा। पहली प्रविष्टि A (1,1) एक्सेस की गई है, सिस्टम मुख्य मेमोरी से कैश में A (1,1), A (2,1), ..., A (8,1) युक्त कैश लाइन लाएगा। । अंतरतम लूप के अगले 8 पुनरावृत्तियों इस डेटा पर बिना किसी अतिरिक्त मुख्य मेमोरी ट्रांसफर के काम करते हैं।

यदि विकल्प में, हम छोरों की संरचना करते हैं ताकि स्तंभ सूचकांक अंतरतम लूप में भिन्न हो, तो ए की प्रविष्टियों को ए (1,1), ए (1,2), ए (1,3) में एक्सेस किया जाएगा। ), ... इस मामले में, पहली पहुंच ए (1,1), ए (2,1), ..., ए (8,1) को मुख्य मेमोरी से कैश में लाएगी, लेकिन 7/8 इन प्रविष्टियों का उपयोग नहीं किया जाएगा। दूसरे पुनरावृत्ति में ए (1,2) तक पहुंच तब मुख्य मेमोरी से एक और 8 प्रविष्टियां लाएगा, और इसी तरह। जब तक कोड मैट्रिक्स की पंक्ति 2 पर काम करने के लिए चारों ओर हो जाता है, तब तक ए (2,1) प्रविष्टि को अन्य आवश्यक डेटा के लिए रास्ता बनाने के लिए कैश से बाहर निकाला जा सकता है। नतीजतन, कोड आवश्यक रूप से 8 गुना अधिक ट्रैफ़िक उत्पन्न कर रहा है।

कुछ अनुकूलन करने वाले कंपाइलर इस समस्या से बचने के लिए स्वचालित रूप से लूप्स को पुनर्गठन करने में सक्षम हैं।

मैट्रिक्स गुणन और गुणन के लिए कई संख्यात्मक रैखिक बीजगणित एल्गोरिदम को प्रोग्रामिंग भाषा के आधार पर पंक्ति-प्रमुख या स्तंभ-प्रमुख आदेश योजना के साथ कुशलता से काम करने के लिए अनुकूलित किया जा सकता है। इसे गलत तरीके से करने से प्रदर्शन पर महत्वपूर्ण नकारात्मक प्रभाव पड़ सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.