2010-01-25 12 views
39

का उपयोग कर अधिकतम रिकर्सन गहराई को मारना पृष्ठभूमि: मैं न्यूनतम निर्माण एल्गोरिदम का उपयोग करके एक शब्दकोश का प्रतिनिधित्व करने के लिए एक त्रिभुज का निर्माण कर रहा हूं। इनपुट सूची 4.3 एम यूटीएफ -8 स्ट्रिंग्स है, जो लीक्सिकोग्राफिक रूप से क्रमबद्ध है। परिणामी ग्राफ विश्वकोश है और इसकी अधिकतम गहराई 638 नोड्स है। मेरी स्क्रिप्ट की पहली पंक्ति रिकर्सन सीमा को 1100 से sys.setrecursionlimit() पर सेट करती है।पिकल/सीपीकल

समस्या: मैं डिस्क पर अपने त्रिभुज को क्रमबद्ध करने में सक्षम होना चाहता हूं, इसलिए मैं इसे स्क्रैच (लगभग 22 मिनट) के पुनर्निर्माण के बिना स्मृति में लोड कर सकता हूं। मैंने टेक्स्ट और बाइनरी प्रोटोकॉल दोनों के साथ pickle.dump() और cPickle.dump() दोनों की कोशिश की है।

File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 649, in save_dict 
    self._batch_setitems(obj.iteritems()) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 663, in _batch_setitems 
    save(v) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 725, in save_inst 
    save(stuff) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 286, in save 
    f(self, obj) # Call unbound method with explicit self 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/pickle.py", line 648, in save_dict 
    self.memoize(obj) 
RuntimeError: maximum recursion depth exceeded 

मेरे डेटा संरचनाओं अपेक्षाकृत आसान है: trie एक शुरुआत के राज्य का संदर्भ होता है, और कुछ तरीकों को परिभाषित करता है हर बार, मैं एक ढेर का पता लगाने कि ऐसा दिखाई देता हो। dfa_state में एक बुलियन फ़ील्ड, एक स्ट्रिंग फ़ील्ड, और लेबल से राज्य में एक शब्दकोश मैपिंग शामिल है।

मैं pickle की आंतरिक कार्यप्रणाली से बहुत परिचित नहीं हूं - क्या मेरी अधिकतम रिकर्सन गहराई को कुछ एन के लिए त्रिभुज की गहराई के बराबर/बराबर होना चाहिए? या यह किसी और चीज के कारण हो सकता है जो मुझे अनजान है?

अद्यतन: रिकर्सन गहराई को 3000 तक सेट करने में मदद नहीं मिली, इसलिए यह एवेन्यू आशाजनक नहीं दिख रहा है।

अपडेट 2: आप लोग सही थे; मुझे लगता है कि अचार डिफ़ॉल्ट रिकर्सन सीमाओं के कारण एक छोटी घोंसले की गहराई का उपयोग करेगा, यह समझने में मुझे कम-से-कम देखा जा रहा था। 10,000 चाल है।

उत्तर

26

the docs से:

एक बेहद पुनरावर्ती डेटा संरचना अचार के लिए अधिकतम प्रत्यावर्तन गहराई से अधिक हो सकता कोशिश कर रहा है, एक RuntimeError इस मामले में बढ़ा दी जाएगी। आप sys.setrecursionlimit() के साथ सावधानीपूर्वक इस सीमा को बढ़ा सकते हैं।

हालांकि आपका त्रिभुज कार्यान्वयन सरल हो सकता है, लेकिन यह रिकर्सन का उपयोग करता है और लगातार डेटा संरचना में परिवर्तित होने पर समस्याएं पैदा कर सकता है।

मेरी सिफारिश यह देखने के लिए रिकर्सन सीमा को जारी रखेगी कि क्या आप जिस डेटा के साथ काम कर रहे हैं उसके लिए ऊपरी सीमा है और आप जिस त्रिज्या कार्यान्वयन का उपयोग कर रहे हैं।

अन्य तो है कि, आप अपने पेड़ कार्यान्वयन को बदलने, "कम पुनरावर्ती" होने के लिए यदि संभव हो तो कोशिश कर सकते हैं, या एक अतिरिक्त कार्यान्वयन (अपने कार्यान्वयन में उपयोग अचार और shelves) डेटा हठ में निर्मित है कि लिखें। उम्मीद है कि

3

डबल-चेक करें कि आपकी संरचना वास्तव में विश्वकोश है।

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

भी अपने trie का एक छोटा सा संस्करण चुनने का प्रयास करें। यदि अचार मर जाता है भले ही यह केवल तीन-अक्षर वाले शब्दों को संग्रहित कर रहा हो, तो आप जानते हैं कि आपके त्रिभुज के साथ कुछ मौलिक समस्या है और अचार नहीं है। लेकिन अगर यह केवल तब होता है जब आप 10k शब्दों को संग्रहीत करने का प्रयास करते हैं, तो यह अचार में प्लेटफ़ॉर्म सीमा की गलती हो सकती है।

+0

मुझे पता चला है कि बढ़ती रिकर्सन सीमा का उपयोग स्मृति उपयोग पर एक मजबूत प्रभाव है ... – fccoelho

+0

http://svn.python.org/projects/python/trunk/Tools/scripts/find_recursionlimit.py आपको ऊपरी ढूंढने में मदद कर सकता है आपके हार्डवेयर की सीमा – Ullullu

8

अचार को आपके त्रिभुज को फिर से चलाने की आवश्यकता है। यदि पिकल कार्य करने के लिए केवल 5 स्तरों के फ़ंक्शन कॉल का उपयोग कर रहा है तो कार्य करने के लिए गहराई 638 की त्रिज्या को 3000 से अधिक स्तर की आवश्यकता होगी।

एक बड़ी संख्या का प्रयास करें, रिकर्सन सीमा वास्तव में उपयोगकर्ताओं की सुरक्षा के लिए है अगर रिकर्सन एक अनंत छेद में पड़ता है तो बहुत लंबा इंतजार करना पड़ता है।

अचार ठीक चक्र संभालती है, तो यह बात भले ही आपके trie वहाँ में एक चक्र था नहीं है

+0

यदि यह सही ढंग से चक्रों को संभालती है तो यह अनंत छेद में कैसे गिर सकती है? – YvesgereY

+0

@ जॉन ओप्शनलस्मिथ, 'अचार' एक अनंत छेद में नहीं आता है, लेकिन सामान्य मामले में रिकर्सन कर सकते हैं, इसलिए जब रिकर्सन बहुत गहरा हो जाता है तो यह अपवाद उठाता है। –

3

ढेर आकार भी तुम सिर्फ sys.setrecursionlimit का उपयोग करते हैं segfault

को रोकने के लिए resource.setrlimit के साथ बढ़ जाना चाहिए , यदि आप लिनक्स कर्नेल द्वारा अनुमत अधिकतम स्टैक आकार तक पहुंचते हैं, तो भी आप segfault कर सकते हैं। Setting stacksize in a python script

import pickle 
import resource 
import sys 

print resource.getrlimit(resource.RLIMIT_STACK) 
print sys.getrecursionlimit() 

max_rec = 0x100000 

# May segfault without this line. 0x100 is a guess at the size of each stack frame. 
resource.setrlimit(resource.RLIMIT_STACK, [0x100 * max_rec, resource.RLIM_INFINITY]) 
sys.setrecursionlimit(max_rec) 

a = [] 
# 0x10 is to account for subfunctions called inside `pickle`. 
for i in xrange(max_rec/0x10): 
    a = [a] 
print pickle.dumps(a, -1) 

यह भी देखें:: मेरे लिए What is the maximum recursion depth in Python, and how to increase it?

डिफ़ॉल्ट अधिकतम मूल्य 8Mb है

यह मान के रूप में उल्लेख किया resource.setrlimit साथ बढ़ाया जा सकता है।

उबंटू 16.10, पायथन 2.7.12 पर परीक्षण किया गया।

0

मेरी ज़रूरतें कुछ हद तक तत्काल थीं इसलिए मैंने अपनी शब्दकोश को .txt प्रारूप में सहेजकर इस समस्या को हल किया। केवल एक चीज यह है कि जब आप अपनी फाइल को फिर से लोड करते हैं तो आपको इसे वापस एक शब्दकोश में बदलना होगा।

import json 

# Saving the dictionary 
with open('filename.txt', 'w') as file_handle: 
    file_handle.write(str(dictionary)) 

# Importing the .txt file 
with open('filename.txt', 'r') as file_handle: 
    f = '"' + file_handle.read() + '"' 

# From .txt file to dictionary 
dictionary = eval(json.loads(f)) 

यदि यह काम नहीं करता है तो आप जेसन प्रारूप का उपयोग करके शब्दकोश निर्यात करने का प्रयास कर सकते हैं।

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

  • कोई संबंधित समस्या नहीं^_^