दिलचस्प पोस्ट
पांडा: पहले से मौजूद कॉलम से की गई मानों के साथ डेटाफ्रेम में दो नए कॉलम बनाएं 'स्थायी रूप से जुड़े' और 'गतिशील रूप से जुड़े' से क्या मतलब है? रूबी द्वारा सभी सबस्ट्रिंग प्राप्त करने के लिए स्ट्रिंग को विभाजित करने का सबसे अच्छा तरीका क्या है? गिट मर्ज डिफ़ॉल्ट मर्ज संदेश का उपयोग नहीं करता है, डिफ़ॉल्ट संदेश के साथ संपादक खोलता है कीबोर्ड को खारिज करने का आसान तरीका? एंड्रॉइड डीबग मॉनिटर पदानुक्रम दृश्य नहीं दिखा रहा है क्या विंडोज के लिए unistd.h के लिए एक प्रतिस्थापन (दृश्य सी) है? JavaScript में URL को पार्स करें मेरी iPhone ऐप में तिथि करने के लिए स्ट्रिंग कन्वर्ट बहुत सारे खुले आंकड़े के बारे में चेतावनी क्यों यह सरल .नेट कंसोल ऐप में इतने धागे हैं? JQuery के ".val ()" का उपयोग करते हुए एक छिपे हुए फ़ील्ड के मूल्य को सेट करें काम नहीं करता है WindowsFormsHost हमेशा WPF तत्व से सबसे ऊपर है कार्य के भीतर जावास्क्रिप्ट और ऑपरेटर jQuery के AJAX सफलता कॉलबैक फ़ंक्शन परिभाषा

डिस्क पर सहेजे बिना अजगर सबप्रोसेसेस के बीच मैं बड़े numpy arrays कैसे पार करूं?

डिस्क का उपयोग किए बिना दो अजगर सबप्रोसेसेस के बीच डेटा का एक बड़ा हिस्सा पारित करने का एक अच्छा तरीका है? यहां एक कार्टून का उदाहरण है जिसे मैं पूरा करने की उम्मीद कर रहा हूं:

import sys, subprocess, numpy cmdString = """ import sys, numpy done = False while not done: cmd = raw_input() if cmd == 'done': done = True elif cmd == 'data': ##Fake data. In real life, get data from hardware. data = numpy.zeros(1000000, dtype=numpy.uint8) data.dump('data.pkl') sys.stdout.write('data.pkl' + '\\n') sys.stdout.flush()""" proc = subprocess.Popen( #python vs. pythonw on Windows? [sys.executable, '-c %s'%cmdString], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for i in range(3): proc.stdin.write('data\n') print proc.stdout.readline().rstrip() a = numpy.load('data.pkl') print a.shape proc.stdin.write('done\n') 

यह सबप्रोसेक्शन बनाता है जो एक संकीर्ण सरणी उत्पन्न करता है और डिस्क को सरणी सहेजता है। मूल प्रक्रिया तब डिस्क से सरणी को लोड करती है। यह काम करता हैं!

समस्या यह है कि हमारा हार्डवेयर डिस्क को पढ़ने / लिखने से 10x तेज डेटा उत्पन्न कर सकता है। क्या एक अजगर प्रक्रिया से डेटा स्थानांतरित करने के लिए एक अन्य विशुद्ध रूप से स्मृति में, यहां तक ​​कि डेटा की एक कॉपी किए बिना भी एक तरीका है? क्या मैं पास-टू-रेफरेंस जैसी कुछ कर सकता हूँ?

विशुद्ध रूप से स्मृति में डेटा को स्थानांतरित करने का मेरा पहला प्रयास बहुत घटिया है:

 import sys, subprocess, numpy cmdString = """ import sys, numpy done = False while not done: cmd = raw_input() if cmd == 'done': done = True elif cmd == 'data': ##Fake data. In real life, get data from hardware. data = numpy.zeros(1000000, dtype=numpy.uint8) ##Note that this is NFG if there's a '10' in the array: sys.stdout.write(data.tostring() + '\\n') sys.stdout.flush()""" proc = subprocess.Popen( #python vs. pythonw on Windows? [sys.executable, '-c %s'%cmdString], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for i in range(3): proc.stdin.write('data\n') a = numpy.fromstring(proc.stdout.readline().rstrip(), dtype=numpy.uint8) print a.shape proc.stdin.write('done\n') 

यह बहुत धीमा है (डिस्क को बचाने के मुकाबले बहुत धीमा) और बहुत, बहुत नाजुक। एक बेहतर तरीका होना चाहिए!

मैं 'सबप्रोसेस' मॉड्यूल से शादी नहीं कर रहा हूं, जब तक कि डेटा लेने की प्रक्रिया माता-पिता के आवेदन को ब्लॉक नहीं करती है। मैंने संक्षेप में 'बहु प्रसंस्करण' की कोशिश की, लेकिन सफलता के बिना अभी तक।

पृष्ठभूमि: हमारे पास हार्डवेयर का एक टुकड़ा है जो सीटीपीस बफ़र्स की श्रृंखला में ~ 2 जीबी / एस डेटा तक उत्पन्न करता है। इन बफ़र्स को संभालने के लिए अजगर कोड के पास हाथों से भरा है, केवल जानकारी की बाढ़ से निपटना। मैं सूचनाओं के इस प्रवाह को समन्वयित करना चाहता हूं, जिसमें कई अन्य टुकड़ों के साथ एक 'मास्टर' कार्यक्रम में एक साथ चल रहे हैं, बिना एक दूसरे को अवरुद्ध करने वाले सबप्रोसेस मेरा वर्तमान दृष्टिकोण डिस्क को सहेजने से पहले सबप्रोसेस में डेटा को थोड़ा नीचे उबाल करना है, लेकिन 'मास्टर' प्रक्रिया से पूर्ण मोंटी को पारित करना अच्छा होगा

Solutions Collecting From Web of "डिस्क पर सहेजे बिना अजगर सबप्रोसेसेस के बीच मैं बड़े numpy arrays कैसे पार करूं?"

कोड जो किंगटन के बारे में अधिक जानकारी के लिए चारों ओर googling, मैं numpy-sharedmem पैकेज मिल गया इस एमएमपी / मल्टीप्रोसेसिंग ट्यूटोरियल से देखते हुए यह एक ही बौद्धिक विरासत (संभवतः एक ही लेखक – मुझे यकीन नहीं है) को साझा करना लगता है।

साझामैम मॉड्यूल का उपयोग करके, आप एक साझा-स्मृति numpy सरणी (भयानक!) बना सकते हैं, और इसे इस तरह से बहु-प्रसंस्करण के साथ उपयोग कर सकते हैं:

 import sharedmem as shm import numpy as np import multiprocessing as mp def worker(q,arr): done = False while not done: cmd = q.get() if cmd == 'done': done = True elif cmd == 'data': ##Fake data. In real life, get data from hardware. rnd=np.random.randint(100) print('rnd={0}'.format(rnd)) arr[:]=rnd q.task_done() if __name__=='__main__': N=10 arr=shm.zeros(N,dtype=np.uint8) q=mp.JoinableQueue() proc = mp.Process(target=worker, args=[q,arr]) proc.daemon=True proc.start() for i in range(3): q.put('data') # Wait for the computation to finish q.join() print arr.shape print(arr) q.put('done') proc.join() 

चलने की पैदावार

 rnd=53 (10,) [53 53 53 53 53 53 53 53 53 53] rnd=15 (10,) [15 15 15 15 15 15 15 15 15 15] rnd=87 (10,) [87 87 87 87 87 87 87 87 87 87] 

असल में, आप केवल प्रक्रियाओं के बीच मेमोरी का एक ब्लॉक साझा करना चाहते हैं और इसे एक अंडाकार सरणी के रूप में देखना चाहते हैं, है ना?

उस मामले में, इस पर एक नज़र डालें (नम्मी-हौस पर चर्चा में पोस्ट किया गया, थोड़ी देर पहले, न मेरा काम)। कुछ ऐसे ही लागूकरण (कुछ और लचीला) हैं, लेकिन वे सभी इस सिद्धांत का प्रयोग करते हैं।

 # "Using Python, multiprocessing and NumPy/SciPy for parallel numerical computing" # Modified and corrected by Nadav Horesh, Mar 2010 # No rights reserved import numpy as N import ctypes import multiprocessing as MP _ctypes_to_numpy = { ctypes.c_char : N.dtype(N.uint8), ctypes.c_wchar : N.dtype(N.int16), ctypes.c_byte : N.dtype(N.int8), ctypes.c_ubyte : N.dtype(N.uint8), ctypes.c_short : N.dtype(N.int16), ctypes.c_ushort : N.dtype(N.uint16), ctypes.c_int : N.dtype(N.int32), ctypes.c_uint : N.dtype(N.uint32), ctypes.c_long : N.dtype(N.int64), ctypes.c_ulong : N.dtype(N.uint64), ctypes.c_float : N.dtype(N.float32), ctypes.c_double : N.dtype(N.float64)} _numpy_to_ctypes = dict(zip(_ctypes_to_numpy.values(), _ctypes_to_numpy.keys())) def shmem_as_ndarray(raw_array, shape=None ): address = raw_array._obj._wrapper.get_address() size = len(raw_array) if (shape is None) or (N.asarray(shape).prod() != size): shape = (size,) elif type(shape) is int: shape = (shape,) else: shape = tuple(shape) dtype = _ctypes_to_numpy[raw_array._obj._type_] class Dummy(object): pass d = Dummy() d.__array_interface__ = { 'data' : (address, False), 'typestr' : dtype.str, 'descr' : dtype.descr, 'shape' : shape, 'strides' : None, 'version' : 3} return N.asarray(d) def empty_shared_array(shape, dtype, lock=True): ''' Generate an empty MP shared array given ndarray parameters ''' if type(shape) is not int: shape = N.asarray(shape).prod() try: c_type = _numpy_to_ctypes[dtype] except KeyError: c_type = _numpy_to_ctypes[N.dtype(dtype)] return MP.Array(c_type, shape, lock=lock) def emptylike_shared_array(ndarray, lock=True): 'Generate a empty shared array with size and dtype of a given array' return empty_shared_array(ndarray.size, ndarray.dtype, lock) 

दूसरे जवाबों से, ऐसा लगता है कि नमूनी-साझा करने का तरीका रास्ता तय करना है

हालांकि, यदि आपको शुद्ध अजगर समाधान की आवश्यकता है, या एक्सटेंशन स्थापित करने, साइथॉन या समानता (बड़ी) परेशानी है, तो आप निम्न कोड का उपयोग करना चाहेंगे जो कि नावाद के कोड का एक सरलीकृत संस्करण है:

 import numpy, ctypes, multiprocessing _ctypes_to_numpy = { ctypes.c_char : numpy.dtype(numpy.uint8), ctypes.c_wchar : numpy.dtype(numpy.int16), ctypes.c_byte : numpy.dtype(numpy.int8), ctypes.c_ubyte : numpy.dtype(numpy.uint8), ctypes.c_short : numpy.dtype(numpy.int16), ctypes.c_ushort : numpy.dtype(numpy.uint16), ctypes.c_int : numpy.dtype(numpy.int32), ctypes.c_uint : numpy.dtype(numpy.uint32), ctypes.c_long : numpy.dtype(numpy.int64), ctypes.c_ulong : numpy.dtype(numpy.uint64), ctypes.c_float : numpy.dtype(numpy.float32), ctypes.c_double : numpy.dtype(numpy.float64)} _numpy_to_ctypes = dict(zip(_ctypes_to_numpy.values(), _ctypes_to_numpy.keys())) def shm_as_ndarray(mp_array, shape = None): '''Given a multiprocessing.Array, returns an ndarray pointing to the same data.''' # support SynchronizedArray: if not hasattr(mp_array, '_type_'): mp_array = mp_array.get_obj() dtype = _ctypes_to_numpy[mp_array._type_] result = numpy.frombuffer(mp_array, dtype) if shape is not None: result = result.reshape(shape) return numpy.asarray(result) def ndarray_to_shm(array, lock = False): '''Generate an 1D multiprocessing.Array containing the data from the passed ndarray. The data will be *copied* into shared memory.''' array1d = array.ravel(order = 'A') try: c_type = _numpy_to_ctypes[array1d.dtype] except KeyError: c_type = _numpy_to_ctypes[numpy.dtype(array1d.dtype)] result = multiprocessing.Array(c_type, array1d.size, lock = lock) shm_as_ndarray(result)[:] = array1d return result 

आप इसे इस तरह प्रयोग करेंगे:

  1. उपयोग करें sa = ndarray_to_shm(a) को साझा मल्टीप्रोसेसिंग में परिवर्तित करें। sa = ndarray_to_shm(a)
  2. साझा एरे को पारित करने के लिए, किसी अन्य प्रक्रिया में somefunc को कॉल करने के लिए multiprocessing.Process(target = somefunc, args = (sa, ) (और start , शायद join ) का उपयोग करें।
  3. कुछ में, साझा डेटा के लिए इंगित एक a = shm_as_ndarray(sa) पाने के लिए a = shm_as_ndarray(sa) का उपयोग करें। (असल में, आप मूल प्रक्रिया में उसी तरह से करना चाहते हैं, जिससे sa बना सकें, ताकि दो डेटा को उसी डेटा का संदर्भ दे सके।)

एफ़एक्सिक्स, आपको लॉक को सही पर सेट करने की आवश्यकता नहीं है, क्योंकि shm_as_ndarray लॉकिंग का उपयोग किसी भी तरह से नहीं करेगा। अगर आपको लॉकिंग की आवश्यकता है, तो आप लॉक को ट्रू पर सेट कर सकते हैं और प्राप्त करने / रिलीज के लिए sa

इसके अलावा, यदि आपकी सरणी 1-आयामी नहीं है, तो आप आकृति को सा के साथ स्थानांतरित करना चाहेंगे (जैसे args = (sa, a.shape) )

इस समाधान का फायदा यह है कि उसे अतिरिक्त पैकेज या विस्तार मॉड्यूल की आवश्यकता नहीं है, मल्टी प्रोकक्शन (जो कि मानक लाइब्रेरी में है) को छोड़कर।

धागे का उपयोग करें लेकिन मुझे लगता है कि आप जीआईएल के साथ समस्याओं को लेकर जा रहे हैं।

इसके बजाय: अपने ज़हर का चयन करें

मैं उन MPI कार्यान्वयनों से जानता हूं जो मैं साथ काम करता हूं, वे नोड-संचार के लिए साझा स्मृति का उपयोग करते हैं उस मामले में आपको अपना सिंक्रनाइज़ेशन कोड करना होगा।

2 जीबी / एस लगता है जैसे आपको अपने वास्तविक समय की कमी और उपलब्ध मुख्य मेमोरी के आधार पर सबसे अधिक "आसान" तरीके से समस्याएं मिलेंगी।

धागे का उपयोग करें आपको संभवतः जीआईएल के साथ समस्या नहीं होगी।

जीआईएल केवल पायथन कोड को प्रभावित करता है, C / Fortran / Cython समर्थित पुस्तकालयों पर नहीं। अधिकांश नमूनों के संचालन और सी-समर्थित वैज्ञानिक पायथन स्टैक का एक अच्छा हिस्सा जीआईएल को रिहा करता है और कई कोर पर सिर्फ ठीक काम कर सकता है। इस blogpost जीआईएल और वैज्ञानिक पायथन अधिक गहराई में चर्चा करता है।

संपादित करें

धागे का उपयोग करने के लिए सरल तरीके में threading मॉड्यूल और multiprocessing.pool.ThreadPool . multiprocessing.pool.ThreadPool