पंडों में अजीब बग और मल्टीथ्रेडिंग के बारे में नम्पी


25

अधिकांश Numpy का फ़ंक्शन डिफ़ॉल्ट रूप से मल्टीथ्रेडिंग को सक्षम करेगा।

उदाहरण के लिए, मैं एक 8-कोर इंटेल सीपीयू वर्कस्टेशन पर काम करता हूं, अगर मैं एक स्क्रिप्ट चलाता हूं

import numpy as np    
x=np.random.random(1000000)
for i in range(100000):
    np.sqrt(x)

लिनक्स topचलने के दौरान 800% सीपीयू उपयोग दिखाएगा, यहां छवि विवरण दर्ज करें जिसका अर्थ है कि सुन्न स्वचालित रूप से पता लगाता है कि मेरे कार्य केंद्र में 8 कोर हैं, और np.sqrtगणना में तेजी लाने के लिए स्वचालित रूप से सभी 8 कोर का उपयोग करें।

हालांकि, मुझे एक अजीब बग मिला। अगर मैं कोई स्क्रिप्ट चलाता हूं

import numpy as np
import pandas as pd
df=pd.DataFrame(np.random.random((10,10)))
df+df
x=np.random.random(1000000)
for i in range(100000):
    np.sqrt(x)

सीपीयू का उपयोग 100% है !!। इसका मतलब यह है कि यदि आप किसी भी प्रकार्य समारोह को चलाने से पहले दो पांडा डेटाफ्रेम को जोड़ते हैं, तो बिना किसी चेतावनी के ऑटो मल्टीथ्रेडिंग फीचर बिना किसी चेतावनी के चला जाता है! यह बिल्कुल उचित नहीं है, क्यों पांडस डेटाफ्रेम गणना नम्पी थ्रेडिंग सेटिंग को प्रभावित करेगा? यह एक बग है? इसके आसपास कैसे काम करें?यहां छवि विवरण दर्ज करें


पुनश्च:

मैं लिनक्स perfउपकरण का उपयोग करके आगे खुदाई करता हूं ।

पहला स्क्रिप्ट शो चल रहा है

यहां छवि विवरण दर्ज करें

जबकि दूसरा स्क्रिप्ट शो चल रहा है

यहां छवि विवरण दर्ज करें

तो दोनों लिपि शामिल है libmkl_vml_avx2.so, जबकि पहली लिपि में अतिरिक्त शामिल है libiomp5.soजो ओपनएमपी से संबंधित है।

और चूंकि vml का अर्थ है इंटेल वेक्टर गणित पुस्तकालय, इसलिए vml doc के अनुसार मुझे लगता है कि कम से कम कार्य नीचे सभी स्वचालित रूप से गुणा किए गए हैं

यहां छवि विवरण दर्ज करें


मुझे यकीन नहीं है कि मैं आपके सवाल को समझ सकता हूँ। क्या आप विस्तार से समझा सकते हैं?
AMC

@AMC मैंने अपनी पोस्ट अपडेट की, आशा है कि यह अब स्पष्ट है
user15964

मुझे लगता है कि एनपी, पांडा, संस्करण, सीपीयू, ओएस प्रकार की तरह अधिक जानकारी की आवश्यकता है ... मैं अपनी मशीन पर पुन: पेश नहीं कर सकता। यह दोनों कोड में कई सीपीयू का उपयोग नहीं करता है।
शिकारी

@hunzter ओके, यहाँ पर दिया गया है। पुनश्च। मैं एनाकोंडा का उपयोग करता हूं
user15964

1
क्या आप इसे जाँच सकते हैं:import numpy as np import pandas as pd import os os.environ["MKL_NUM_THREADS"] = '4' print(os.environ["MKL_NUM_THREADS"]) df=pd.DataFrame(np.random.random((10,10))) df+df print(os.environ["MKL_NUM_THREADS"]) a = np.random.random((20000000, 3)) b = np.random.random((3, 30)) for _ in range(10): c = np.dot(a, b)
Stas Buzuluk

जवाबों:


13

पंडों numexprने कुछ ऑपरेशनों की गणना करने के लिए हुड के नीचे का उपयोग किया, और numexprजब यह आयात किया जाता है , तो vml 1 के लिए अधिकतम थ्रेड की संख्या सेट करता है :

# The default for VML is 1 thread (see #39)
set_vml_num_threads(1)

और इसे भावdf+df में मूल्यांकन किए जाने पर पांडा द्वारा आयात किया जाता है :

from pandas.core.computation.check import _NUMEXPR_INSTALLED

if _NUMEXPR_INSTALLED:
   import numexpr as ne

हालांकि, एनाकोंडा वितरण के रूप में भी इस तरह के कार्यों के लिए VML-कार्यक्षमता का उपयोग करता sqrt, sin, cosऔर इतने पर - और एक बार numexpr1 पर सेट VML-धागे की अधिकतम संख्या, numpy-कार्यों को अब उपयोग में चलाना।

समस्या को gbb में आसानी से देखा जा सकता है (आपकी धीमी स्क्रिप्ट का उपयोग करके):

>>> gdb --args python slow.py
(gdb) b mkl_serv_domain_set_num_threads
function "mkl_serv_domain_set_num_threads" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (mkl_serv_domain_set_num_threads) pending.
(gbd) run
Thread 1 "python" hit Breakpoint 1, 0x00007fffee65cd70 in mkl_serv_domain_set_num_threads () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
(gdb) bt 
#0  0x00007fffee65cd70 in mkl_serv_domain_set_num_threads () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
#1  0x00007fffe978026c in _set_vml_num_threads(_object*, _object*) () from /home/ed/anaconda37/lib/python3.7/site-packages/numexpr/interpreter.cpython-37m-x86_64-linux-gnu.so
#2  0x00005555556cd660 in _PyMethodDef_RawFastCallKeywords () at /tmp/build/80754af9/python_1553721932202/work/Objects/call.c:694
...
(gdb) print $rdi
$1 = 1

यानी हम देख सकते हैं, numexprथ्रेड्स की संख्या 1 पर सेट की गई है। जिसे बाद में vml-sqrt फ़ंक्शन कहा जाता है:

(gbd) b mkl_serv_domain_get_max_threads
Breakpoint 2 at 0x7fffee65a900
(gdb) (gdb) c
Continuing.

Thread 1 "python" hit Breakpoint 2, 0x00007fffee65a900 in mkl_serv_domain_get_max_threads () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
(gdb) bt
#0  0x00007fffee65a900 in mkl_serv_domain_get_max_threads () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
#1  0x00007ffff01fcea9 in mkl_vml_serv_threader_d_1i_1o () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
#2  0x00007fffedf78563 in vdSqrt () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_lp64.so
#3  0x00007ffff5ac04ac in trivial_two_operand_loop () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/core/_multiarray_umath.cpython-37m-x86_64-linux-gnu.so

तो हम देख सकते हैं कि vpy का उपयोग vml का कार्यान्वयन है, vdSqrtजो mkl_vml_serv_threader_d_1i_1oयह तय करने के लिए उपयोग करता है कि क्या गणना समानांतर में की जानी चाहिए और यह थ्रेड्स की संख्या देखती है:

(gdb) fin
Run till exit from #0  0x00007fffee65a900 in mkl_serv_domain_get_max_threads () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
0x00007ffff01fcea9 in mkl_vml_serv_threader_d_1i_1o () from /home/ed/anaconda37/lib/python3.7/site-packages/numpy/../../../libmkl_intel_thread.so
(gdb) print $rax
$2 = 1

रजिस्टर %raxमें थ्रेड्स की अधिकतम संख्या है और यह 1 है।

अब हम vml-threads की संख्या बढ़ाने केnumexpr लिए उपयोग कर सकते हैं , अर्थात:

import numpy as np
import numexpr as ne
import pandas as pd
df=pd.DataFrame(np.random.random((10,10)))
df+df

#HERE: reset number of vml-threads
ne.set_vml_num_threads(8)

x=np.random.random(1000000)
for i in range(10000):
    np.sqrt(x)     # now in parallel

अब कई कोर का उपयोग किया जाता है!


आपको बहुत - बहुत धन्यवाद! अंत में, एक महान जवाब सभी बताते हैं। अंत में, यह numexprदृश्य के पीछे है।
user15964

सहमत .. अच्छी खुदाई! अगला सवाल हालांकि .. क्यों नंबर्स पुश थ्रेड 1 की गिनती करता है? संभवतः अस्थिरता / थ्रेड-सुरक्षित मुद्दों के कारण? 8 तक की गिनती को पीछे धकेलने के बजाय, यह NumPy के थ्रेड-सुरक्षित / स्थिर संस्करण पर जाने के लिए सुरक्षित हो सकता है। शायद नवीनतम और सबसे बड़ी NumPy के साथ इस चर की जांच करने के लिए भी अच्छा है अगर वास्तव में इसकी आवश्यकता नहीं है, इसलिए तकनीकी रूप से एक बग है।
एंड्रयू ऐटेंस


2

सुन्न को देखते हुए, ऐसा लग रहा है, हुड के नीचे यह मल्टीथ्रेडिंग के साथ / बंद मुद्दों पर पड़ा है, और आप किस संस्करण का उपयोग कर रहे हैं, उसके आधार पर जब आप ne.set_vml_num_breads () को टक्कर दे रहे हैं, तो क्रैश देखना शुरू कर सकते हैं।

http://numpy-discussion.10968.n7.nabble.com/ANN-NumExpr-2-7-0-Release-td47414.html

मुझे अपना सिर इधर-उधर करने की जरूरत है कि यह अजगर इंटरप्रेटर में कैसे चिपके हुए है, आपके कोड उदाहरण को देखते हुए जहां यह किसी तरह से कई जाहिरा तौर पर तुल्यकालिक / आदेशित कॉल करने की अनुमति देता है np.sqrt () समानांतर में आगे बढ़ने के लिए। मुझे लगता है कि अगर अजगर दुभाषिया हमेशा एक वस्तु का संदर्भ दे रहा है, जब यह स्टैक पॉप करता है, और आपके उदाहरण में सिर्फ उन संदर्भों को पिच कर रहा है और उन्हें किसी भी तरह से असाइन या हेरफेर नहीं कर रहा है तो यह ठीक होगा। लेकिन अगर बाद के लूप पुनरावृत्तियों पिछले वाले पर निर्भर करते हैं तो यह कम स्पष्ट लगता है कि ये कैसे सुरक्षित रूप से समानांतर किए जा सकते हैं। यकीनन मौन विफलता / गलत परिणाम दुर्घटनाओं से भी बदतर परिणाम है।


हाय, एंड्रयू Atrens, आप लगभग वहाँ हैं। यह ne.set_vml_num_threads () की समस्या है। मेरे मुद्दे पर आपके समर्पित समय के लिए बहुत-बहुत धन्यवाद।
user15964

हैप्पी ट्रेल्स :)
एंड्रयू ऐर्टेंस

0

मुझे लगता है कि आपका प्रारंभिक आधार गलत हो सकता है -

आपने कहा: जिसका अर्थ है कि सुन्न स्वतः पता लगाता है कि मेरे कार्य केंद्र में 8 कोर हैं, और np.sqrt स्वचालित रूप से गणना में तेजी लाने के लिए सभी 8 कोर का उपयोग करते हैं।

एक एकल फ़ंक्शन np.sqrt () यह अनुमान नहीं लगा सकता है कि यह आंशिक रूप से पूरा होने से पहले इसे कैसे लागू करेगा या वापस लौटाएगा। अजगर में समानता तंत्र हैं, लेकिन कोई भी स्वचालित नहीं है।

अब, कहा जा रहा है कि, अजगर दुभाषिया समानांतरता के लिए लूप को अनुकूलित करने में सक्षम हो सकता है, जो कि आप जो देख रहे हैं वह हो सकता है, लेकिन मैं दृढ़ता से संदेह करता हूं कि यदि आप इस लूप को निष्पादित करने के लिए दीवार-घड़ी के समय को देखते हैं तो यह नहीं होगा भले ही आप (जाहिरा तौर पर) 8 कोर या 1 कोर का उपयोग कर रहे हों।

अद्यतन: टिप्पणियों के एक छोटे से अधिक पढ़ने के बाद ऐसा लगता है जैसे कि आप देख रहे बहु-कोर व्यवहार अजगर इंटरप्रेटर के एनाकोंडा वितरण से संबंधित है। मैंने देख लिया, लेकिन इसके लिए कोई स्रोत कोड नहीं मिल पा रहा था, लेकिन ऐसा लगता है कि अजगर लाइसेंस प्रकाशित करने के लिए अपने परिवर्तनों की आवश्यकता के बिना इंटरप्रेटर के डेरिवेटिव को संकलित करने और वितरित करने के लिए संस्थाओं (anaconda.com) की अनुमति देता है।

मुझे लगता है कि आप एनाकोंडा लोगों तक पहुंच सकते हैं - जो व्यवहार आप देख रहे हैं, यह जानने के बिना कि क्या वे दुभाषिया में बदल गए हैं, यह जानने के लिए मुश्किल होगा।

यह देखने के अनुकूलन के साथ / बिना दीवार घड़ी के समय की एक त्वरित जांच करें कि क्या यह वास्तव में 8x तेज है - भले ही आपको वास्तव में 1 के बजाय सभी 8 कोर काम कर रहे हों, यह जानना अच्छा होगा कि क्या परिणाम वास्तव में 8x हैं तेजी से या अगर वहाँ उपयोग कर रहे हैं spinlocks जो अभी भी एक म्यूटेक्स पर धारावाहिक कर रहे हैं।


1
हाय, एंड्रयू Atrens। लेकिन समानांतरकरण अजगर द्वारा नहीं किया जाता है, यह एनाकोंडा सुन्न के बैकेंड द्वारा किया जाता है जो कि इंटेल एमकेएल है। और हाँ, मैंने अंक पर एक मुद्दा खोला है, उन्होंने मुझे एनाकोंडा पर एक मुद्दा खोलने का सुझाव दिया, और मैंने ऐसा किया। हालाँकि, मुझे एनाकोंडा से एक सप्ताह के लिए एक भी उत्तर नहीं मिला। इसलिए शायद उन्होंने मेरी रिपोर्ट को नजरअंदाज कर दिया ...
user15964

यह एनाकोंडा संस्करण के साथ एक मुद्दा है / अजगर दुभाषिया की रिहाई - उनका संस्करण ओपनमैप का उपयोग करता है जबकि मानक पायथन रिलीज नहीं करता है।
एंड्रयू एटेंस

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

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