मान लीजिए मेरे पास एक पांडा डेटाफ्रेम है और एक फ़ंक्शन जिसे मैं प्रत्येक पंक्ति पर लागू करना चाहता हूं। मैं df.apply(apply_fn, axis=1)
पर कॉल कर सकता हूं, जिसमें df
के आकार में समय रैखिक होना चाहिए। या मैं प्रत्येक टुकड़े पर अपने फ़ंक्शन को कॉल करने के लिए df
विभाजित कर सकता हूं और pool.map
का उपयोग कर सकता हूं, और फिर परिणामों को जोड़ सकता हूं।पांडा के साथ मल्टीप्रोसेसिंग का उपयोग क्यों नाटकीय गति के लिए लागू होता है?
मैं pool.map
का उपयोग कर मोटे तौर पर पूल में प्रक्रियाओं की संख्या के बराबर होने के लिए से speedup कारक उम्मीद कर रहा था (new_execution_time = original_execution_time/एन अगर एन प्रोसेसर का उपयोग कर - और कि शून्य भूमि के ऊपर यह सोचते है)।
इसके बजाए, इस खिलौने उदाहरण में, समय 4 प्रोसेसर का उपयोग करते समय लगभग 2% (0.005272/0.230757) तक गिर जाता है। मैं सबसे अच्छा 25% की उम्मीद कर रहा था। क्या चल रहा है और मैं क्या समझ नहीं पा रहा हूं?
import numpy as np
from multiprocessing import Pool
import pandas as pd
import pdb
import time
n = 1000
variables = {"hello":np.arange(n), "there":np.random.randn(n)}
df = pd.DataFrame(variables)
def apply_fn(series):
return pd.Series({"col_5":5, "col_88":88,
"sum_hello_there":series["hello"] + series["there"]})
def call_apply_fn(df):
return df.apply(apply_fn, axis=1)
n_processes = 4 # My machine has 4 CPUs
pool = Pool(processes=n_processes)
t0 = time.process_time()
new_df = df.apply(apply_fn, axis=1)
t1 = time.process_time()
df_split = np.array_split(df, n_processes)
pool_results = pool.map(call_apply_fn, df_split)
new_df2 = pd.concat(pool_results)
t2 = time.process_time()
new_df3 = df.apply(apply_fn, axis=1) # Try df.apply a second time
t3 = time.process_time()
print("identical results: %s" % np.all(np.isclose(new_df, new_df2))) # True
print("t1 - t0 = %f" % (t1 - t0)) # I got 0.230757
print("t2 - t1 = %f" % (t2 - t1)) # I got 0.005272
print("t3 - t2 = %f" % (t3 - t2)) # I got 0.229413
मैंने उपरोक्त कोड को सहेजा और python3 my_filename.py
का उपयोग करके इसे चलाया।
पीएस मुझे एहसास है कि इस खिलौने उदाहरण में new_df
लागू किए बिना, अधिक सरल तरीके से बनाया जा सकता है। मुझे एक और जटिल apply_fn
के साथ समान कोड लागू करने में दिलचस्पी है जो केवल कॉलम नहीं जोड़ता है।
धन्यवाद, आपको सही होना चाहिए। मुझे समझ में नहीं आता कि क्या हो रहा है, यद्यपि। ऐसा क्यों होता है भले ही 'time.process_time()' कॉल मल्टीप्रोसेसिंग कॉल के बाहर हों? क्या ऐसा इसलिए है क्योंकि 'time.process_time()' केवल माता-पिता प्रक्रिया के CPU समय को वापस कर रहा है? – Adrian
@ एड्रियन क्षमा करें, मैं गलत था - बाल प्रक्रियाओं को 'process_time' के साथ गड़बड़ नहीं हुई थी। गलतफहमी के लिए खेद है। मैं जवाब अद्यतन करता हूँ। – ptrj