Python 3.4 की तुलना में Python 3.5 में str.translate ज्यादा तेज क्यों है?


116

मैं text.translate()पायथन 3.4 का उपयोग करके किसी दिए गए स्ट्रिंग से अवांछित पात्रों को हटाने की कोशिश कर रहा था ।

न्यूनतम कोड है:

import sys 
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))

यह उम्मीद के मुताबिक काम करता है। हालाँकि जब Python 3.4 और Python 3.5 में निष्पादन किया जाता है तो वही कार्यक्रम एक बड़ा अंतर देता है।

समय की गणना करने के लिए कोड है

python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); "   "s.translate(mapper)"

पाइथन 3.4 प्रोग्राम में 1.3ms लगते हैं जबकि पायथन 3.5 में एक ही प्रोग्राम केवल 26.4μs लेता है ।

पायथन 3.5 में क्या सुधार हुआ है जो पायथन 3.4 की तुलना में इसे तेज बनाता है?


11
जब हम प्रदर्शन के बारे में बात कर रहे हैं, तो क्या इस तरह अपना मैपर उत्पन्न करना बेहतर नहीं होगा dict.fromkeys(ord(c) for c in '@#$'):?
थॉमस के

1
@ThomasK मुझे पता चला कि इससे एक महत्वपूर्ण अंतर आया। हां आपका रास्ता बेहतर है।
भार्गव राव

क्या आपका मतलब 50x तेज था?
अस्वच्छता

@assylias मैंने 1300 - 26.4 किया और फिर 1300 से विभाजित किया। मुझे लगभग 95% मिला, इसलिए मैंने लिखा :) यह वास्तव में 50x से अधिक तेज है ... लेकिन क्या मेरी गणना गलत है? मैं गणित में थोड़ा कमजोर हूं। मैं जल्द ही गणित सीखूंगा। :)
भार्गव राव

3
आपको इसे गोल करना चाहिए: 26/1300 = 2% इसलिए तेज़ संस्करण को धीमे संस्करण द्वारा लिया गया समय का केवल 2% लगता है => यह 50x तेज़ है।
अस्वच्छता

जवाबों:


148

टीएल; डीआर - आईएसएसयूई 21118


लंबी कहानी है

जोश रोसेनबर्ग ने पाया कि str.translate()समारोह की तुलना में बहुत धीमी है bytes.translate, उन्होंने कहा कि एक मुद्दा उठाया :

पायथन 3 में, str.translate()आमतौर पर एक प्रदर्शन निराशा है, अनुकूलन नहीं।

क्यों था str.translate() धीमी थी?

का मुख्य कारण str.translate()बहुत धीमी गति से था कि लुकिंग पायथन डिक्शनरी में हुआ करता था।

maketransइस समस्या का उपयोग बदतर बना दिया। समान दृष्टिकोण का उपयोग करके bytesफास्ट टेबल लुकअप के लिए 256 वस्तुओं के सी सरणी का निर्माण होता है। इसलिए उच्च स्तर के उपयोग अजगर dictबना देता हैstr.translate() अजगर 3.4 में बहुत धीमी गति से।

अब क्या हुआ?

पहला दृष्टिकोण एक छोटा पैच जोड़ना था, Translate_writer , हालांकि गति में वृद्धि उस मनभावन नहीं थी। जल्द ही एक और पैच fast_translate का परीक्षण किया गया और इसमें 55% तक स्पीडअप के बहुत अच्छे परिणाम मिले।

फ़ाइल से देखा जा सकता है कि मुख्य बदलाव यह है कि पायथन डिक्शनरी लुकअप को C लेवल लुकअप में बदल दिया जाता है।

गति अब लगभग समान हैं bytes

                                unpatched           patched

str.translate                   4.55125927699919    0.7898181750006188
str.translate from bytes trans  1.8910855210015143  0.779950579000797

यहां एक छोटा नोट यह है कि प्रदर्शन में वृद्धि केवल ASCII स्ट्रिंग्स में प्रमुख है।

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

पहले ASCII बनाम गैर-अस्की का उपयोग लगभग एक ही हुआ करता था, हालांकि अब हम प्रदर्शन में एक महान परिवर्तन देख सकते हैं।

जैसा कि इस उत्तर में देखा गया है यह 71.6μs से 2.33μs तक का सुधार हो सकता है

निम्न कोड यह प्रदर्शित करता है

python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
100000 loops, best of 3: 2.3 usec per loop
python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 117 usec per loop

python3 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 91.2 usec per loop
python3 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
10000 loops, best of 3: 101 usec per loop

परिणामों का सारणीकरण:

         Python 3.4    Python 3.5  
Ascii     91.2          2.3 
Unicode   101           117

13
यह कमिट्स में से एक है: github.com/python/cpython/commit/…
filmor

नोट: ascii बनाम गैर-असिसी मामला प्रदर्शन में काफी भिन्न हो सकता है। यह 55% के बारे में नहीं है : जैसा कि आपके उत्तर से पता चलता है, गति 1000% s हो सकती है
jfs 19

तुलना: python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"(अस्सी) बनाम python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"(गैर-अस्की)। उत्तरार्द्ध ज्यादा (10x) धीमा है।
jfs

@ जेएफ ओह, मैं इसे अब समझ गया हूं। मैंने आपका कोड 3.4 और 3.5 दोनों के लिए चलाया। मुझे गैर-एससीआई सामान के लिए तेजी से Py3.4 मिल रहा है। क्या यह संयोग से है? परिणाम dpaste.com/15FKSDQ
भार्गव राव

3.5 से पहले, एएससी और गैर-असिसी दोनों मामले संभवत: यूनिकोड के लिए समान हैं .translate(), अर्थात केवल पायथॉन 3.5 में एएससीआई का मामला बहुत तेज है (आपको bytes.translate()वहां प्रदर्शन की आवश्यकता नहीं है )।
jfs
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.