2008-08-30 28 views
8

मेरे पास एक सूचना पुनर्प्राप्ति अनुप्रयोग है जो 10 मिलियन बिट्स के आदेश पर बिट एरे बनाता है। सरणी में "सेट" बिट्स की संख्या सभी स्पष्ट रूप से सभी सेट से व्यापक रूप से भिन्न होती है। वर्तमान में, मैं एक सीधी-आगे बिट सरणी (java.util.BitSet) का उपयोग कर रहा हूं, इसलिए मेरे प्रत्येक बिट सरणी में कई मेगाबाइट लगते हैं।बिट सरणी के कुछ विकल्प क्या हैं?

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

  • प्रत्येक चरम पर कौन सी संरचनाएं अच्छी हो सकती हैं?
  • क्या बीच में कोई है?

    1. बिट्स केवल एक बार सेट कर रहे हैं, और सूचकांक क्रम में:

यहाँ कुछ कमी या संकेत दिए हैं।

  • मुझे 100% सटीकता की आवश्यकता है, इसलिए ब्लूम फ़िल्टर की तरह कुछ पर्याप्त नहीं है।
  • सेट के निर्माण के बाद, मुझे "सेट" बिट्स पर कुशलतापूर्वक पुन: सक्रिय करने में सक्षम होना चाहिए।
  • बिट्स को यादृच्छिक रूप से वितरित किया जाता है, इसलिए रन-लम्बाई – एन्कोडिंग एल्गोरिदम बिट इंडेक्स की एक साधारण सूची से कहीं बेहतर नहीं होने की संभावना है।
  • मैं स्मृति उपयोग को अनुकूलित करने की कोशिश कर रहा हूं, लेकिन गति अभी भी कुछ वजन रखती है।
  • ओपन सोर्स जावा कार्यान्वयन के साथ कुछ उपयोगी है, लेकिन सख्ती से जरूरी नहीं है। मैं मौलिक सिद्धांतों में अधिक रुचि रखता हूं।

    उत्तर

    16

    जब तक डेटा सही मायने में यादृच्छिक और एक सममित 1/0 वितरण किया गया है, तो यह सिर्फ एक दोषरहित डेटा संपीड़न समस्या बन जाता है और CCITT समूह 3 काले और सफेद (यानी के लिए इस्तेमाल किया संपीड़न के बहुत अनुरूप है: बाइनरी) फैक्स छवियों। सीसीआईटीटी समूह 3 एक हफमैन कोडिंग योजना का उपयोग करता है। फैक्स के मामले में वे हफमैन कोड के एक निश्चित सेट का उपयोग कर रहे हैं, लेकिन किसी दिए गए डेटा सेट के लिए, आप संपीड़न अनुपात को बेहतर बनाने के लिए प्रत्येक डेटा सेट के लिए कोड का एक विशिष्ट सेट जेनरेट कर सकते हैं। जब तक आप केवल बिट्स को अनुक्रमिक रूप से एक्सेस करने की आवश्यकता रखते हैं, जैसा कि आपने बताया है, यह एक बहुत ही कुशल दृष्टिकोण होगा। यादृच्छिक पहुंच कुछ अतिरिक्त चुनौतियों का निर्माण करेगी, लेकिन आप शायद सरणी में विभिन्न ऑफ़सेट पॉइंट्स में बाइनरी सर्च ट्री इंडेक्स जेनरेट कर सकते हैं जो आपको वांछित स्थान के करीब पहुंचने की अनुमति देगी और फिर वहां से चलेगी।

    नोट: Huffman योजना अभी भी अच्छी तरह से काम करता है, भले ही डेटा यादृच्छिक है, जब तक कि 1/0 वितरण पूरी तरह से भी नहीं है। यही है, वितरण भी कम, संपीड़न अनुपात बेहतर है।

    अंत में, यदि बिट्स भी वितरण के साथ वास्तव में यादृच्छिक हैं, तो श्री क्लाउड शैनन के अनुसार, आप किसी भी योजना का उपयोग करके इसे किसी भी महत्वपूर्ण राशि को संपीड़ित करने में सक्षम नहीं होंगे।

    +0

    सुंदर समाधान देखें। यह भी तेज़ हो सकता है क्योंकि स्मृति लोड आज बहुत महंगा है। –

    0

    सीधे आगे लापरवाही संपीड़न जाने का रास्ता है।इसे खोजने योग्य बनाने के लिए आपको अपेक्षाकृत छोटे ब्लॉक को संपीड़ित करना होगा और ब्लॉक की सरणी में एक अनुक्रमणिका बनाना होगा। इस अनुक्रमणिका में प्रत्येक ब्लॉक में प्रारंभिक बिट का थोड़ा ऑफसेट हो सकता है।

    0

    त्वरित combinatoric सबूत है कि तुम सच में अधिक स्थान नहीं बचा सकते हैं:

    मान लीजिए आप n/2 बिट्स n कुल बिट्स में से 1 करने के लिए सेट की एक मनमाना सबसेट है। आपके पास (एन एन/2) संभावनाएं हैं। Stirling's formula का उपयोग करके, यह लगभग 2^एन/वर्ग (एन) * वर्ग (2/पीआई) है। यदि हर संभावना समान रूप से संभव है, तो कम संभावनाओं को कम प्रतिनिधित्व देने का कोई तरीका नहीं है। तो हमें लॉग_2 (एन एन/2) बिट्स की आवश्यकता है, जो एन - (1/2) लॉग (एन) बिट्स के बारे में है।

    यह स्मृति की बहुत अच्छी बचत नहीं है। उदाहरण के लिए, यदि आप n = 2^20 (1 मेग) के साथ काम कर रहे हैं, तो आप केवल 10 बिट्स बचा सकते हैं। यह सिर्फ इसके लायक नहीं है।

    यह सब कहकर, यह भी असंभव लगता है कि वास्तव में कोई भी उपयोगी डेटा वास्तव में यादृच्छिक है। यदि आपके डेटा में कोई और संरचना है, तो शायद अधिक आशावादी उत्तर है।

    1

    उत्तर के लिए धन्यवाद। यह वही है जो मैं गतिशील रूप से सही विधि चुनने की कोशिश करने जा रहा हूं:

    मैं एक पारंपरिक बिट सरणी में पहले एन हिट एकत्र करूंगा, और समरूपता के आधार पर तीन तरीकों में से एक का चयन करूंगा यह नमूना

    • नमूना अत्यधिक विषम है, तो मैं बस एक सूची में सेट बिट्स (या शायद दूरी अगले बिट करने के लिए) के लिए अनुक्रमित संग्रहीत करेंगे।
    • यदि नमूना अत्यधिक सममित है, मैं एक पारंपरिक बिट सरणी का उपयोग जारी रखूंगा।
    • यदि नमूना मामूली सममित है, तो मैं हानि रहित संपीड़न विधि जैसे हफमैन कोडिंग suggested by InSciTekJeff का उपयोग करूंगा।

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

    यह संभव है (और वास्तव में मैं उम्मीद कर रहा हूं) कि मध्यम संपीड़न विधि हमेशा सूची या बिट सरणी या दोनों से बेहतर होगी। हो सकता है कि मैं उच्च या निम्न समरूपता के लिए अनुकूलित हफमैन कोड का एक सेट चुनकर इसे प्रोत्साहित कर सकता हूं। फिर मैं सिस्टम को सरल बना सकता हूं और बस दो तरीकों का उपयोग कर सकता हूं।

    1

    एक और संपीड़न सोचा:

    बिट सरणी पागल लंबी नहीं है, तो आप ऐसे Huffman के रूप में किसी भी पुनरावृत्ति एन्कोडिंग, उपयोग करने से पहले Burrows-Wheeler transform लागू करने की कोशिश कर सकता है। एक निष्पक्ष कार्यान्वयन ओ (एन^2) मेमोरी (डी) संपीड़न और ओ (एन^2 लॉग एन) समय के दौरान डिकंप्रेस करने के लिए ले जाएगा - लगभग निश्चित रूप से शॉर्टकट भी होने चाहिए। लेकिन अगर आपके डेटा पर कोई अनुक्रमिक संरचना है, तो यह वास्तव में हफमैन एन्कोडिंग में मदद करनी चाहिए।

    आप उस विचार को समय/स्मृति उपयोग को और अधिक व्यावहारिक रखने के लिए एक समय में एक ब्लॉक पर भी लागू कर सकते हैं।समय पर एक ब्लॉक का उपयोग करने से आप अनुक्रमिक रूप से पढ़ रहे/लिख रहे हैं, तो आप हमेशा डेटा संरचना को संपीड़ित रखने की अनुमति दे सकते हैं।

    4

    मैं दृढ़ता से हफमैन कोडिंग के स्थान पर रेंज एन्कोडिंग का उपयोग करने पर विचार करता हूं। आम तौर पर, रेंज एन्कोडिंग हफमैन कोडिंग की तुलना में असमानता का अधिक प्रभावी ढंग से उपयोग कर सकती है, लेकिन यह विशेष रूप से तब होता है जब वर्णमाला आकार इतना छोटा होता है। असल में, जब "मूल वर्णमाला" बस 0 और 1 एस होता है, तो हफमैन को केवल एक ही संपीड़न मिल सकता है, उन प्रतीकों को जोड़कर - जो वास्तव में सीमा एन्कोडिंग करेगा, अधिक प्रभावी ढंग से।

    +0

    धन्यवाद एंटेयस, मैंने वास्तव में पहले से ही रेंज कोडिंग में देखा था, क्योंकि स्वीकृत उत्तर ने हफमैन कोडिंग को लापरवाही संपीड़न के केवल एक उदाहरण के रूप में उद्धृत किया था। हालांकि, हफमैन को कार्यान्वित करना आसान है और मामूली असममित इनपुट पर अच्छी तरह से काम करता है। अत्यधिक असममित इनपुट के लिए, रन-लम्बाई विधियां अच्छी हैं। – erickson

    2

    शायद आपके लिए बहुत देर हो चुकी है, लेकिन कोशिशों के आधार पर स्पैस बिट एरे (लापरवाह) और अन्य डेटा प्रकारों के लिए एक बहुत तेज़ और मेमोरी कुशल लाइब्रेरी है। Judy arrays

    +0

    धन्यवाद बिल। मुझे पहले जूडी सरणी के बारे में सुनना याद है लेकिन मैं उनके बारे में पूरी तरह से भूल गया था। मैं उन पर एक और नजर डालेगा। – erickson

    संबंधित मुद्दे