বেশ কয়েকটি প্রক্রিয়ার মধ্যে ফলাফলের সারি ভাগ করে নেওয়া


96

multiprocessingমডিউলটির ডকুমেন্টেশন দেখায় যে কীভাবে কোনও প্রক্রিয়ায় একটি সারি পাস করতে হবে multiprocessing.Process। তবে আমি কীভাবে অ্যাসিক্রোনাস কর্মী প্রক্রিয়া শুরু করার সাথে একটি সারি ভাগ করতে পারি apply_async? আমার গতিশীল যোগদান বা অন্য কিছু দরকার নেই, কেবল শ্রমিকদের পক্ষে (বারবার) তাদের ফলাফলগুলি বেসে ফেরত দেওয়ার একমাত্র উপায়।

import multiprocessing
def worker(name, que):
    que.put("%d is done" % name)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=3)
    q = multiprocessing.Queue()
    workers = pool.apply_async(worker, (33, q))

এই কর্ম বিফল হয়: RuntimeError: Queue objects should only be shared between processes through inheritance। আমি এর অর্থ কী তা আমি বুঝতে পেরেছি, এবং পিকিং / আনপিকলিংয়ের (এবং সমস্ত বিশেষ উইন্ডোজ বিধিনিষেধের) পরিবর্তে উত্তরাধিকারী হওয়ার পরামর্শটি আমি বুঝতে পারি understand কিন্তু কিভাবে কি আমি একটি উপায় যে কাজ কিউ পাস? আমি উদাহরণ খুঁজে পাচ্ছি না, এবং আমি বেশ কয়েকটি বিকল্প চেষ্টা করেছি যা বিভিন্ন উপায়ে ব্যর্থ হয়েছিল। অনুগ্রহ করে সাহায্য করবেন?

উত্তর:


138

আপনার সারি পরিচালনা করতে এবং এটি বিভিন্ন কর্মীদের কাছে অ্যাক্সেসযোগ্য করার জন্য মাল্টিপ্রসেসিং ব্যবহারের চেষ্টা করুন an

import multiprocessing
def worker(name, que):
    que.put("%d is done" % name)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=3)
    m = multiprocessing.Manager()
    q = m.Queue()
    workers = pool.apply_async(worker, (33, q))

এটা এটা করেছে, ধন্যবাদ! আমার আসল কোডটিতে অ্যাসিঙ্ক কলটি নিয়ে কোনও সম্পর্কযুক্ত সমস্যা ছিল, তাই আমি আপনার উত্তরেও এই অনুলিপিটি অনুলিপি করেছিলাম।
অ্যালেক্সিস

17
কোন ব্যাখ্যা কেন queue.Queue()এই জন্য উপযুক্ত নয়?
mrgloom

4
@ এমআরগ্লুম: queue.Queueমেমোরি লকগুলি ব্যবহার করে থ্রেডিংয়ের জন্য নির্মিত হয়েছিল। মাল্টিপ্রসেস পরিবেশে, প্রতিটি উপ-প্রসেসগুলি queue.Queue()তাদের নিজস্ব মেমরি স্পেসে একটি উদাহরণের নিজস্ব অনুলিপি পাবে , কারণ সাবপ্রসেসগুলি মেমরি ভাগ করে না (বেশিরভাগ ক্ষেত্রে))
লিওরোকেল

4
@alexis একাধিক কর্মী এতে ডেটা ?োকানোর পরে ম্যানেজার ()। কুইউ () থেকে উপাদানগুলি কীভাবে পাবেন?
এমএসএস


14

multiprocessing.Poolইতিমধ্যে একটি ভাগ ফলাফল-সারি আছে, অতিরিক্ত জড়িত কোন প্রয়োজন নেই Manager.Queue। হুডের নীচে Manager.Queueএকটি queue.Queue(মাল্টিথ্রেডিং-সারি) যা পৃথক সার্ভার-প্রক্রিয়াতে অবস্থিত এবং প্রক্সিগুলির মাধ্যমে উন্মুক্ত। এটি পুলের অভ্যন্তরীণ সারির তুলনায় অতিরিক্ত ওভারহেড যুক্ত করে। পুলের নেটিভ রেজাল্ট হ্যান্ডলিংয়ের উপর নির্ভর করার বিপরীতে, ফলাফলগুলিও Manager.Queueঅর্ডার দেওয়ার গ্যারান্টিযুক্ত নয়।

কর্মী প্রক্রিয়াগুলি দিয়ে শুরু হয় না.apply_async() , আপনি তাত্ক্ষণিকভাবে কাজ করার আগেই এটি ঘটে Pool। আপনি যখন কল করবেন তখন যা শুরু হয়pool.apply_async() তা একটি নতুন "কাজ"। পুলের কর্মী-প্রক্রিয়াগুলি multiprocessing.pool.workerহুডের নীচে - ফাংশনটি চালায় । এই ফাংশনটি নতুন "কর্ম" পুলে অভ্যন্তরীণ উপর স্থানান্তরিত প্রক্রিয়াকরণের যত্ন নেয় Pool._inqueueএবং ফলাফল উপর পিতা বা মাতা ফিরে পাঠানোর Pool._outqueue। আপনার নির্দিষ্ট funcমধ্যেই মৃত্যুদন্ড কার্যকর করা হবে multiprocessing.pool.workerfuncকেবল returnকিছু আছে এবং ফলাফলটি স্বয়ংক্রিয়ভাবে পিতামাতার কাছে ফেরত পাঠানো হবে।

.apply_async() তাত্ক্ষণিকভাবে ( অবিচ্ছিন্নভাবে ) কোনও AsyncResultবস্তু (উরফের জন্য ApplyResult) প্রদান করে। .get()আসল ফলাফল পাওয়ার জন্য আপনাকে সেই অবজেক্টে কল করা (অবরুদ্ধ করা) দরকার । আর একটি বিকল্প হ'ল একটি কলব্যাক ফাংশনটি নিবন্ধন করা , যা ফলাফল প্রস্তুত হওয়ার সাথে সাথেই বরখাস্ত হয়।

from multiprocessing import Pool

def busy_foo(i):
    """Dummy function simulating cpu-bound work."""
    for _ in range(int(10e6)):  # do stuff
        pass
    return i

if __name__ == '__main__':

    with Pool(4) as pool:
        print(pool._outqueue)  # DEMO
        results = [pool.apply_async(busy_foo, (i,)) for i in range(10)]
        # `.apply_async()` immediately returns AsyncResult (ApplyResult) object
        print(results[0])  # DEMO
        results = [res.get() for res in results]
        print(f'result: {results}')       

উদাহরণ আউটপুট:

<multiprocessing.queues.SimpleQueue object at 0x7fa124fd67f0>
<multiprocessing.pool.ApplyResult object at 0x7fa12586da20>
result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

দ্রষ্টব্য: timeout-পরিমিতি নির্দিষ্টকরণের ফলে কর্মীর মধ্যে টাস্কটির .get()প্রকৃত প্রসেসিং বন্ধ হবে না, এটি কেবলমাত্র একটি উত্থাপনের দ্বারা অপেক্ষমান পিতামাতাকে অবরোধ মুক্ত করে multiprocessing.TimeoutError


আকর্ষণীয়, আমি প্রথম সুযোগটি চেষ্টা করে দেখব। এটি অবশ্যই 2012 সালে এইভাবে কাজ করেনি
অ্যালেক্সিস

@ অ্যালেক্সিস পাইথন ২.7 (২০১০) প্রাসঙ্গিকভাবে এখানে কেবল প্রসঙ্গ পরিচালক এবং এর জন্য- error_callbackপরিমিতিটি অনুপস্থিত apply_async, তাই এর পরে এটি খুব বেশি পরিবর্তন হয়নি।
ডারকনাট

আমি কলব্যাক ফাংশনটি সর্বাধিক দরকারী বলে মনে করেছি, বিশেষত যখন এখানে বর্ণিত হিসাবে অ্যাসিঙ্ক ফলাফলগুলি সংগ্রহের জন্য নিয়মিত তালিকা ব্যবহারের অনুমতি দেওয়ার জন্য একটি আংশিক ফাংশনের সাথে মিলিত হয়েছিল; gist.github.com/Glench/5789879
user5359531
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.