मैं एक कक्षा के लिए एक परियोजना कर रहा हूं जो स्मृति में अधिकतर 0 मानों के साथ एक विशाल मैट्रिक्स को संग्रहीत करने और उस पर कुछ मैट्रिक्स गणित करने पर केंद्रित है। मैट्रिक्स तत्वों को संग्रहीत करने के लिए मेरा पहला विचार HashMap
का उपयोग करना था, और बड़ी मात्रा में स्मृति का उपयोग करने से बचने के लिए केवल उन तत्वों को स्टोर करें जो गैर-शून्य हैं।यह क्यों है कि, मेरी कुंजी में अधिक '1' बिट्स, हैश मैप में जितना अधिक समय लगता है?
मैं HashMap
के लिए एक कुंजी बनाना चाहता था जो कि तत्व में पंक्ति और कॉलम संख्या दोनों का प्रतिनिधित्व करेगा, जब मैंने मानचित्र में उस प्रविष्टि को एक्सेस किया था, तो मैं दोनों मानों को फिर से निकाल सकता था। मुझे जावा के साथ-साथ सी # - सी # में नहीं पता है, मैं और Column
सदस्यों के साथ बनाउंगा, लेकिन जावा में मुझे जल्दी से एहसास हुआ कि उपयोगकर्ता मान प्रकार नहीं हैं। एक समय सीमा के साथ मैं एक सुरक्षित शर्त के साथ गया और Key
एक लंबा बनाया। मैंने पहले 32 बिट्स में पंक्ति डेटा (32-बिट int) और पिछले 32 में कॉलम डेटा को कुछ बहुत ही सरल बिट स्थानांतरण का उपयोग करके संग्रहीत किया। [संपादित करें: मैं यह भी ध्यान रखना चाहूंगा कि मेरा हैश मैप एक विशिष्ट प्रारंभिक आकार के साथ शुरू किया गया है जो वास्तव में मेरे द्वारा संग्रहीत मूल्यों की संख्या का प्रतिनिधित्व करता है, जो कभी भी पार नहीं किया जाता है।]
[साइड नोट: कारण मैं चाहता हूं बूट करने के लिए एक छोटे n
फिर पंक्ति/स्तंभ डेटा निकालने के बहुत O(n^2)
से O(n)
को, आव्यूह गुणन की क्षमता बढ़ाने के लिए है, सक्षम होने के लिए और]
क्या मैं इस संरचना को लागू करने के बाद पाया है कि यह एक whopping लेता है एक पाठ फ़ाइल से 23426 x 23426 मैट्रिक्स पढ़ने के लिए 7 सेकंड जिसमें केवल गैर-शून्य तत्व दिए जाते हैं, लेकिन हमें केवल ईज़ीन मानों की गणना करने में 2 सेकंड लगते हैं जिन्हें हमें देने की आवश्यकता होती है! विधियों की चुनिंदा टिप्पणी-आउट के बाद, मैंने निष्कर्ष निकाला है कि इस 7 सेकंड के समय में बड़े पैमाने पर मेरे मूल्यों को HashMap
में संग्रहीत किया जाता है।
public void Set(double value, int row, int column) {
//assemble the long key, placing row and column in adjacent sets of bits
long key = (long)row << SIZE_BIT_MAX; //(SIZE_BIT_MAX is 32)
key += column;
elements.put(key, value);
}
वह मान निर्धारित करने के लिए कोड है। यदि मैं इसके बजाय इस विधि का उपयोग करता हूं:
public void Set(double value, int row, int column) {
//create a distinct but smaller key (around 32 bits max)
long key = (long)(row * matrixSize) + column;
elements.put(key, value);
}
पढ़ने में केवल 2 सेकंड लगते हैं। कुंजी के इन दोनों संस्करणों में प्रत्येक तत्व के लिए अलग-अलग हैं, दोनों लंबे प्रकार के होते हैं, और उनमें से किसी एक को बनाने के लिए वास्तविक कोड जटिलता में न्यूनतम होता है। यह elements.put(key, value)
है जो 7 सेकंड और 2 के बीच अंतर बनाता है।
मेरा प्रश्न है, क्यों? इन महत्वपूर्ण संस्करणों के बीच मैं जो अंतर देखता हूं वह यह है कि पहली बार बिट्स को 1 से अधिक बार सेट किया जाता है, जबकि दूसरे में इसकी सभी 32 बिट्स 0 पर सेट होती हैं। क्या मैं लाल हेरिंग का पीछा कर रहा हूं, या यह काफी नाटकीय अंतर है प्रदर्शन में HashMap.put
विधि में कुछ आंतरिक परिणाम?
एसएससीसीई के बिना, आपको कारण बता देना बहुत मुश्किल है। मेरा अनुमान है कि आप मानचित्र के लिए प्रारंभिक आकार निर्दिष्ट नहीं कर रहे हैं। यह तब बहुत छोटा शुरू होता है और उसे अक्सर आकार बदलना पड़ता है। आकार बदलना, खासकर बड़े नक्शे के लिए बहुत महंगा है। – jackrabbit
प्रारंभिक आकार निर्दिष्ट है और कभी पार नहीं किया गया है। मैं इसे प्रतिबिंबित करने के लिए अपनी पोस्ट संपादित करूंगा। –
शायद छोटे सुधार हो सकते हैं, लेकिन नई क्षमता तक पहुंचने पर लगातार पुन: हैशिंग से बचने के लिए प्रारंभिक तत्वों की उचित संख्या के साथ हैश मैप बनाएं। उदाहरण के लिए, नया हैश मैप <लांग, डबल> (20000); – brettw