उपरोक्त टिप्पणियों से, ऐसा लगता है कि यह 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