সমান্তরালভাবে একটি গোষ্ঠীভুক্ত প্যান্ডাস ডেটাফ্রেমে দক্ষতার সাথে একটি ফাংশন প্রয়োগ করা


89

আমার প্রায়শই খুব বড় DataFrame(মিশ্রিত ডেটা ধরণের) গোষ্ঠীতে একটি ফাংশন প্রয়োগ করা প্রয়োজন এবং একাধিক কোরের সুবিধা নিতে চাই।

আমি গ্রুপগুলি থেকে একটি ইেটরেটর তৈরি করতে এবং মাল্টিপ্রসেসিং মডিউলটি ব্যবহার করতে পারি, তবে এটি দক্ষ নয় কারণ প্রতিটি গ্রুপ এবং ফাংশনের ফলাফলগুলি প্রক্রিয়াগুলির মধ্যে বার্তাপ্রেরণের জন্য অবশ্যই মিশ্রিত করতে হবে।

পিকিং এড়ানো বা DataFrameসম্পূর্ণ অনুলিপি এড়াতে কি কোনও উপায় আছে ? দেখে মনে হচ্ছে মাল্টিপ্রসেসিং মডিউলগুলির ভাগ করা মেমরি ফাংশনগুলি numpyঅ্যারেতে সীমাবদ্ধ । অন্য কোন বিকল্প আছে?


আমি যতদূর জানি, স্বেচ্ছাসেবী বিষয়গুলি ভাগ করার কোনও উপায় নেই। আমি ভাবছি, যদি পিকিংটি মাল্টিপ্রসেসিংয়ের মাধ্যমে লাভের চেয়ে অনেক বেশি সময় নেয়। আপেক্ষিক বাছাইয়ের সময় কমাতে প্রতিটি প্রক্রিয়াটির জন্য আপনার বড় আকারের ওয়ার্ক-প্যাকেজ তৈরির সম্ভাবনার সন্ধান করা উচিত। আরেকটি সম্ভাবনা হ'ল আপনি গ্রুপগুলি তৈরি করার সময় মাল্টিপ্রসেসিং ব্যবহার করতে পারেন।
সেবাস্তিয়ান ওয়ার্ক

4
আমি এর মতো কিছু করি তবে ইউডাব্লুএসজিআই, ফ্লাস্ক এবং প্রিফার্কিং ব্যবহার করে: আমি পান্ডাস ডেটাফ্রেমকে একটি প্রসেসে লোড করি, এটি x বার কাঁটাচামচ করি (এটি একটি ভাগ করে নেওয়া মেমরি অবজেক্ট তৈরি করে) এবং তারপরে সেই প্রক্রিয়াগুলিকে অন্য পাইথন প্রক্রিয়া থেকে কল করি যেখানে আমি ফলাফলগুলি সমাপ্ত করি। এটিএম আমি একটি যোগাযোগের প্রক্রিয়া হিসাবে জেএসএন
ডকস

যাইহোক, আপনি কি কখনও চুনকি দিয়ে এইচডিএফ 5 এ দেখেছেন? (এইচডিএফ 5 সমবর্তী লেখার জন্য সংরক্ষণ করা হয় না, তবে আপনি পৃথক পৃথক ফাইল এবং শেষের
কাঠের

7
এটি 0.14 এর জন্য লক্ষ্যবস্তু হবে, এই সমস্যাটি দেখুন: github.com/pydata/pandas/issues/5751
জেফ

উত্তর:


12

উপরের মন্তব্যগুলি থেকে মনে হয় এটি pandasকিছু সময়ের জন্য পরিকল্পনা করা হয়েছে (একটি আকর্ষণীয়-চেহারা rosettaপ্রকল্পও যা আমি কেবল লক্ষ্য করেছি) just

যাইহোক, যতক্ষণ না প্রতিটি সমান্তরাল কার্যকারিতা এতে অন্তর্ভুক্ত করা হয় ততক্ষণ pandasআমি লক্ষ্য করেছি যে pandasসরাসরি cython+ ওপেনএমপি এবং সি ++ ব্যবহার করে দক্ষ ও মেমরি-অনুলিপি সমান্তরাল বৃদ্ধি লিখতে খুব সহজ ।

সমান্তরাল গ্রুপবাই-সমষ্টি লেখার একটি ছোট উদাহরণ এখানে দেওয়া হয়েছে, যার ব্যবহার এইরকম:

import pandas as pd
import para_group_demo

df = pd.DataFrame({'a': [1, 2, 1, 2, 1, 1, 0], 'b': range(7)})
print para_group_demo.sum(df.a, df.b)

এবং আউটপুট হল:

     sum
key     
0      6
1      11
2      4

সন্দেহ করুন নিঃসন্দেহে, এই সাধারণ উদাহরণটির কার্যকারিতা শেষ পর্যন্ত এর অংশ হবে pandas। কিছু জিনিস, কিন্তু, আরো কিছু সময়ের জন্য ++, সি parallelize প্রাকৃতিক হবে, এবং এটা কত সহজ এই একত্রিত হয় সচেতন হতে হবে গুরুত্বপূর্ণ pandas


এটি করতে, আমি একটি সাধারণ একক উত্স-ফাইল এক্সটেনশন লিখেছিলাম যার কোড অনুসরণ করে।

এটি কিছু আমদানি এবং টাইপ সংজ্ঞা দিয়ে শুরু হয়

from libc.stdint cimport int64_t, uint64_t
from libcpp.vector cimport vector
from libcpp.unordered_map cimport unordered_map

cimport cython
from cython.operator cimport dereference as deref, preincrement as inc
from cython.parallel import prange

import pandas as pd

ctypedef unordered_map[int64_t, uint64_t] counts_t
ctypedef unordered_map[int64_t, uint64_t].iterator counts_it_t
ctypedef vector[counts_t] counts_vec_t

সি ++ unordered_mapটাইপটি একটি একক থ্রেডের vectorযোগফলের জন্য এবং সমস্ত থ্রেডের দ্বারা সংমিশ্রণের জন্য।

এখন ফাংশন sum। এটি দ্রুত অ্যাক্সেসের জন্য টাইপযুক্ত মেমরি ভিউগুলির সাথে শুরু হয় :

def sum(crit, vals):
    cdef int64_t[:] crit_view = crit.values
    cdef int64_t[:] vals_view = vals.values

ফাংশনটি আধা-সমানভাবে থ্রেডগুলিতে ভাগ করে (এখানে হার্ডকড করা 4) এবং প্রতিটি থ্রেডকে তার পরিসীমাতে প্রবেশের যোগফলগুলি যোগ করে চলতে থাকে:

    cdef uint64_t num_threads = 4
    cdef uint64_t l = len(crit)
    cdef uint64_t s = l / num_threads + 1
    cdef uint64_t i, j, e
    cdef counts_vec_t counts
    counts = counts_vec_t(num_threads)
    counts.resize(num_threads)
    with cython.boundscheck(False):
        for i in prange(num_threads, nogil=True): 
            j = i * s
            e = j + s
            if e > l:
                e = l
            while j < e:
                counts[i][crit_view[j]] += vals_view[j]
                inc(j)

থ্রেডগুলি সম্পূর্ণ হয়ে গেলে, ফাংশনটি সমস্ত ফলাফলকে (বিভিন্ন শ্রেণির থেকে) একক মধ্যে একীভূত করে unordered_map:

    cdef counts_t total
    cdef counts_it_t it, e_it
    for i in range(num_threads):
        it = counts[i].begin()
        e_it = counts[i].end()
        while it != e_it:
            total[deref(it).first] += deref(it).second
            inc(it)        

যা বাকি আছে তা হ'ল একটি তৈরি করা DataFrameএবং ফলাফলগুলি ফেরত দেওয়া:

    key, sum_ = [], []
    it = total.begin()
    e_it = total.end()
    while it != e_it:
        key.append(deref(it).first)
        sum_.append(deref(it).second)
        inc(it)

    df = pd.DataFrame({'key': key, 'sum': sum_})
    df.set_index('key', inplace=True)
    return df
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.