2011-11-16 6 views
6

में तेजी से बाइनरी डेटा रूपांतरण पाइथन में एक बाइनरी डेटा स्ट्रिंग को एक संख्यात्मक मान में बदलने के लिए सबसे तेज़ तरीका क्या है?पायथन

मैं struct.unpack_from() का उपयोग कर रहा हूं, लेकिन प्रदर्शन सीमा को मार रहा हूं।

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

स्ट्रीम को नेटवर्क बाइट ऑर्डर (बड़े-एंडियन) में जाना होगा और मशीन छोटी-छोटी है। एक उदाहरण रूपांतरण होगा:

import struct 
network_stream = struct.pack('>I', 0x12345678) 
(converted_int,) = struct.unpack_from('>I', network_stream, 0) 

मैं स्ट्रीम प्रारूप से निपटने, द्विआधारी रूपांतरण के सामान्य मामले से के बारे में कम चिंतित हूँ, और अगर वहाँ unpack को भी एक विकल्प। उदाहरण के लिए, socket.ntohl() को एक int की आवश्यकता होती है, और int() बाइनरी डेटा स्ट्रिंग को परिवर्तित नहीं करेगा।

आपके सुझावों के लिए धन्यवाद!

+0

आप वास्तव में क्या अनपॅक कर रहे हैं? क्या यह संख्यात्मक मूल्यों की एक समान सरणी है? –

+0

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

+1

परीक्षण केस अच्छा होगा – Triptych

उत्तर

2

गति समस्या शायद struct.unpack_from() के कार्यान्वयन में नहीं आती है, लेकिन बाकी सब कुछ में पाइथन को — शब्दकोश लुकअप, ऑब्जेक्ट्स, कॉल फ़ंक्शंस और अन्य कार्यों को करने की आवश्यकता है। आप चीजों को कभी तो थोड़ा unpack_from आयात करके इन शब्दकोश लुकअप में से एक को नष्ट करने के बजाय सीधे हर बार struct मॉड्यूल से यह हो रही द्वारा गति कर सकते हैं:

$ python -m timeit -s "import struct; network_stream = struct.pack('>I', 0x12345678)" "(converted_int,) = struct.unpack_from('>I', network_stream, 0)" 
1000000 loops, best of 3: 0.277 usec per loop 

$ python -m timeit -s "import struct; from struct import unpack_from; network_stream = struct.pack('>I', 0x12345678)" "(converted_int,) = unpack_from('>I', network_stream, 0)" 
1000000 loops, best of 3: 0.258 usec per loop 

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

+0

दिलचस्प विचार। मैं वास्तव में 'संरचना आयात * से' इस्तेमाल किया। इसे आपके उदाहरण की नकल करने के लिए कनवर्ट किया गया और 220 एम कॉल पर 5% प्रदर्शन अंतर भी मिला। कभी उम्मीद नहीं की होगी। धन्यवाद! – CNK

2

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

Cython पायथन के लिए सी एक्सटेंशन उत्पन्न करने का सबसे आसान तरीका है।

एक और आसान तरीका सीपीथॉन को पूरी तरह से pypy के पक्ष में छोड़ना है जो अपने ट्रेसिंग जेआईटी का उपयोग करके उच्च गुणवत्ता वाले, निम्न-स्तरीय कोड उत्पन्न कर सकता है।

एक और चुनौतीपूर्ण लेकिन अधिक प्रत्यक्ष दृष्टिकोण एक सादा सी एक्सटेंशन लिखना है। यह मजेदार नहीं है लेकिन यह मुश्किल नहीं है।

+0

आप इनमें से किन तरीकों का अनुमान लगाएंगे कि निम्नतम कॉल ओवरहेड है? सीटीपी का उपयोग करने से सी एक्सटेंशन अधिक कुशल होने जा रहा है? – CNK

+1

सी एक्सटेंशन हमेशा जीत सकता है क्योंकि इसमें एक बार में कई रूपांतरण करने का मौका होता है (प्रत्येक सूची को सूची में या पुनरावर्तक में प्रति लौटकर)। * Ctypes * दृष्टिकोण प्रति रूपांतरण एक कॉल की एक ग्रैन्युलरिटी है। इसके अतिरिक्त, आप * सभी * डेटा नहीं चाहते हैं, इसलिए एक सी एक्सटेंशन अवांछित मानों को छोड़ सकता है, कई कन्वर्ट/आवंटित/incref/तुलना/कूद/घटाने चक्रों को बचा सकता है। –