我有一个python代码,最初使用sklearn lib训练一个KNN分类器,该分类器产生两个python对象:model和vectorizer。接下来将使用这两个对象对我的数据进行分类(分类)。
接下来,我有一个非常大的数据框,其中包含以下两列(在许多其他列中):
类别:此列将包含上面分类器的输出
data_path:此列是包含上面分类器输入的数据文件的路径
首先,我使用以下df.apply方法处理数据框:
def get_classifier_result(row, model, vectorizer):
with open(row['data_path'], "r") as f:
my_txt = f.readlines()
### run the classifier and classify my_txt input here and generate category value
row['category'] = category
df = pd.read_csv(my_df, sep='\t', header=0)
df.apply(lambda row: get_classifier_result(row, model, vectorizer), axis=1)
此代码花费了24小时才能在功能强大的56核Linux盒式服务器上运行。因此,我尝试使用多处理来加快速度:
import multiprocessing
def get_classifier_result(row, model, vectorizer):
with open(row['data_path'], "r") as f:
my_txt = f.readlines()
### run the classifier and classify my_txt input here and generate category value
row['category'] = category
df = pd.read_csv(my_df, sep='\t', header=0)
p = multiprocessing.Pool(int(40))
for i, row in df.iterrows():
p.apply_async(get_classifier_result, [row, model, vectorizer])
这种方法没有任何改善。在linux框上显示htop会显示所有40个进程都处于S(睡眠)模式,除了其中一个。因此,与df.apply方法一样,我实际上只运行一个进程。
问题似乎与模型和矢量化器对象的大小有关。如果我使用较小的训练数据集对分类器进行训练,以使模型和矢量化器对象的大小减小(比方说减小20倍),则htop将显示所有40个处于就绪模式且正在运行的进程,并且实际上会加速。我尝试使用Manager()并将共享列表中的这两个对象无济于事地传递给进程:
m = Manager()
my_list = [model,vectorizer]
my_shared_list = m.list(my_list)
for i, row in df.iterrows():
p.apply_async(get_classifier_result, [row, my_shared_list])
我什至尝试在池中仅运行3个进程,但结果是相同的(只有一个进程处于活动状态,而另外两个处于睡眠模式)。
为什么只有一个进程以外的所有进程都处于睡眠模式并等待。一个人怎么知道他们还在等什么呢?为什么将参数对象的大小减小到生成过程中可以避免此问题?