क्या% ऑपरेटर का उपयोग किए बिना एक अच्छी तरह से वितरित हैश तालिका को लागू करना संभव है?


11

मैं C # में एक तेज़, अच्छी तरह से वितरित हैश तालिका को लागू करना चाहता हूं। मुझे अपने हैश-कांस्टिंग कार्य को चुनने में परेशानी हो रही है जो एक मनमाना हैश कोड और "बाधा" लेता है, इसलिए इसका उपयोग बाल्टियों को अनुक्रमित करने के लिए किया जा सकता है। मेरे सामने अब तक दो विकल्प हैं:

  • एक तरफ, आप यह सुनिश्चित कर सकते हैं कि आपकी बाल्टियों में हमेशा तत्वों की एक प्रमुख संख्या होती है, और हैश के लिए आपको बस बाल्टियों की संख्या से इसे व्यवस्थित करना है। यह वास्तव में, .NET का शब्दकोश क्या करता हैइस दृष्टिकोण के साथ समस्या यह है कि% का उपयोग करना अन्य कार्यों की तुलना में बेहद धीमा है; अगर आप एग्नर फॉग इंस्ट्रक्शन टेबल को देखते हैं , idiv(जो असेंबली कोड जो% के लिए उत्पन्न होता है) नए इंटेल प्रोसेसर के लिए एक निर्देश विलंबता ~ 25 चक्र है। mulबिटवाइज़ ऑप्स जैसे and, या, के लिए इसकी तुलना लगभग 3 या 1 orसे करें xor

  • दूसरी ओर, आपके पास बाल्टियों की संख्या हमेशा 2 की शक्ति हो सकती है। आपको फिर भी हैश के मापांक की गणना करनी होगी ताकि आप सरणी के बाहर इंडेक्स करने का प्रयास न करें, लेकिन इस बार यह कम खर्चीला होगा । चूँकि 2 की शक्तियाँ % Nबस हैं & (N - 1), अड़चन को एक मास्किंग ऑपरेशन में घटा दिया जाता है, जिसमें केवल 1-2 चक्र होते हैं। यह Google के स्पार्शश द्वारा किया जाता है । इसका नकारात्मक पक्ष यह है कि हम उपयोगकर्ताओं को अच्छी हैश प्रदान करने के लिए गिनती कर रहे हैं; हैश अनिवार्य रूप से हैश के हिस्से को काट देता है, इसलिए हम अब हैश के सभी बिट्स को ध्यान में नहीं रखते हैं। यदि उपयोगकर्ता के हैश को असमान रूप से वितरित किया जाता है, उदाहरण के लिए केवल उच्च बिट्स भरे जाते हैं या निचले बिट्स लगातार समान होते हैं, तो इस दृष्टिकोण में टकराव की दर अधिक होती है।

मैं एक एल्गोरिथ्म की तलाश कर रहा हूं जिसका उपयोग मैं कर सकता हूं जिसमें दोनों दुनिया का सबसे अच्छा है: यह हैश के सभी बिट्स को ध्यान में रखता है, और% का उपयोग करने से भी तेज है। यह जरूरी नहीं कि एक मापांक होना चाहिए, बस कुछ है जो सीमा में होने की गारंटी है 0..N-1(जहां एन बाल्टियों की लंबाई है) और सभी स्लॉट के लिए वितरण भी है। क्या ऐसा एल्गोरिथ्म मौजूद है?

मदद के लिए धन्यवाद।


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


तेजी से (2^N +/- 1)
मोडुलो के लिए

@ मुझे खेद है, लेकिन मुझे यकीन नहीं है कि आपकी टिप्पणी का मेरे पोस्ट के साथ क्या करना है। मैं उपयोगकर्ता द्वारा प्रदान किए गए हैश को नियंत्रित नहीं करता हूं, इसलिए मैं एक बेहतर हैश फ़ंक्शन की तलाश नहीं कर रहा हूं। मुझे यह भी समझ में नहीं आता है कि "दुर्भावनापूर्ण आलसी उपयोगकर्ताओं" से आपका क्या मतलब है।
जेम्स

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

जवाबों:


9

आधुनिक हैश तालिका कार्यान्वयन modulo फ़ंक्शन का उपयोग नहीं करते हैं। वे अक्सर दो आकार की तालिकाओं की शक्ति का उपयोग करते हैं और अनावश्यक बिट्स को काट देते हैं। एक आदर्श हैश फ़ंक्शन यह अनुमति देता है। प्राइम नंबर टेबल साइज के साथ संयुक्त मोडुलो का उपयोग उन दिनों में हुआ जब हैश फ़ंक्शन आमतौर पर खराब होते थे, क्योंकि वे अक्सर नेट विकास में होते हैं। मैं SashHash के बारे में पढ़ने की सलाह देता हूं , एक आधुनिक हैश फ़ंक्शन, फिर कुछ अन्य आधुनिक कार्यों के बारे में पढ़ना, जैसे कि xxHash

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

  • एक संरचना या वर्ग में हैश राज्य का एनकैप्सुलेशन
  • हैश "ऐड" फ़ंक्शंस, जो हैश स्टेट में नया डेटा जोड़ता है (उदाहरण के लिए एक बाइट सरणी, या एक डबल जोड़ें)
  • एक हैश "फाइनल" फ़ंक्शन, हिमस्खलन का उत्पादन करने के लिए
  • हैश परिणाम के इनकैप्सुलेशन - .net में आपको एक विकल्प मिलता है, एक 32 बिट हस्ताक्षरित पूर्णांक।

हैश टेबल इंडेक्स के रूप में हैश फ़ंक्शन परिणाम का उपयोग करने के बारे में अधिक जानकारी के लिए, कृपया इस पेपर में हैशिंग के सार्वभौमिक रूपों की परिभाषाएं देखें: लेस्टर-कम गुणा का उपयोग करके तेज़ 64-बिट सार्वभौमिक हैशिंग


3

सभी बिट्स को रखने के दौरान और उपयोग करने के लिए, XOR का भी उपयोग करें।

एक उदाहरण के लिए, temp = (hash & 0xFFFF) ^ ( hash >> 16); index = (temp & 0xFF) ^ (temp >> 8);

इस उदाहरण के लिए, hash8-बिट प्रभाव का कोई मॉडुलो और सभी 32 बिट्स नहीं है index। हालाँकि, DIV की तुलना में यह तेज़ है या नहीं, कुछ ऐसा है जो बहुत अधिक कारकों पर निर्भर करता है, और यह कुछ मामलों में DIV की तुलना में आसानी से धीमा हो सकता है (जैसे बड़े हैश और छोटे सूचकांक)।


यह हमेशा DIV / IDIV से तेज होने वाला है, हालांकि मुझे नहीं लगता कि यह मेरे सवाल का जवाब देता है- indexरेंज में होगा [0..255]। मुझे रेंज में कुछ चाहिए [0..n-1], जहां nबाल्टी की संख्या है।
जेम्स

@JamesKo लेकिन यदि आप एक शब्दकोश लागू कर रहे हैं, तो आप बाल्टी की संख्या (कुछ हद तक) भी नियंत्रित करते हैं। इसलिए, अभाज्य संख्याओं के बजाय, आप दो की शक्तियाँ चुन सकते हैं। (क्या ऐसा करना वास्तव में एक अच्छा विचार होगा, मैं आपको नहीं बता सकता।)
svick

@svick 2 की शक्तियों के लिए हम एक साधारण मास्क ऑपरेशन कर सकते हैं। जैसा कि प्रश्न में उल्लेख किया गया है, मैं प्राइम नंबर के साथ ऐसा करने का एक सस्ता तरीका ढूंढ रहा हूं ताकि खराब-वितरित हैश को भी हटा दिया जाए।
जेम्स

1

आप इस तथ्य का लाभ उठा सकते हैं कि कई प्रमुख पूर्णांकों में एक मॉड्यूलर गुणक व्युत्क्रम होता है। इस लेख को देखें । आपने अपनी बकेट इंडेक्स प्राइम और मापांक 2 ^ n बनाकर बाधाओं में से एक को संतुष्ट किया है, जो स्वाभाविक रूप से अपेक्षाकृत प्रमुख हैं।

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

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