उपरोक्त टिप्पणियों से, ऐसा लगता है कि यह pandasकुछ समय के लिए योजनाबद्ध है (एक दिलचस्प-दिखने वाली rosettaपरियोजना भी है जिसे मैंने अभी देखा है)।
हालाँकि, जब तक कि हर समानांतर कार्यक्षमता को शामिल नहीं किया जाता 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। कुछ चीजें, हालांकि, कुछ समय के लिए C ++ में समानांतर करना अधिक स्वाभाविक होगा, और यह जानना महत्वपूर्ण है कि इस में संयोजन करना कितना आसान है 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
C ++ 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