Pandas函数在多个线程上运行速度较慢?

时间:2018-02-12 09:46:35

标签: python multithreading pandas python-multithreading

我有一些使用pandas的Python代码,运行大约需要半秒钟。当我连续5次调用main函数(在一个线程上)时,每次调用大约需要半秒钟,因此总共需要2.5秒。但是,当我在5个不同的线程上调用此函数时,每次运行需要2.5秒(总共也是2.5秒,但我预计它总共只有半秒,因为线程并行运行)。

代码基本上是这样做的(简化为了简洁起见):

from pandas.io.json import json_normalize
import pandsas as pd

def build_df():
    event_type_0_lst = {'a': 1, 'b':{'c': 2}}
    event_type_1_lst = {'d': 4, 'e':{'f': 5}}
    event_type_2_lst = {'g': 7, 'h':{'i': 8}}
    type_0_df = pd.DataFrame()
    type_1_df = json_normalize(event_type_1_lst)
    type_1_df[self.event_source_col] = self.event_type_1
    type_2_df = json_normalize(event_type_2_lst)
    type_2_df[self.event_source_col] = self.event_type_2
    all_data_df = pd.concat([type_0_df, type_1_df, type_2_df])
    final_df = all_data_df[
                        [self.ticket_col, self.timestamp_col, self.trigger_col, self.action_col,
                         self.action_uid_col, self.msg_id_col, self.flc_col, self.event_source_col]]
    final_df[self.timestamp_col] = pd.to_datetime(final_df[self.timestamp_col])
    return ticket_df.sort_values(self.timestamp_col).reset_index(drop=True)

def normalize(df):
    df.columns = [col.replace('.', '_') for col in df.columns]
    for col in df.columns:
        df[col] = df[col].astype(str)
        df[col] = df[col].str.encode('unicode-escape').replace('\\x', '<repl>')
        df[col] = df[col].str.encode('unicode-escape').replace('\n', '<repl>')
    return df


def handle_request():
    df = build_df()
    return normalize(df)

可以从Web服务器(使用handle_request包的ThreadPoolExecutor)或从独立的python脚本调用函数concurrent.futures(使用threading包和标准方法创建线程),并在两种情况下重现该问题。我运行此功能的机器有8个核心,应该足够5个线程。

当我运行此功能时,我收到以下警告:

SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
FutureWarning: sort(columns=....) is deprecated, use sort_values(by=.....)
  df_sorted = df.sort(col_order_by, ascending=True)

我认为它与此问题没有任何关联,但我会将其粘贴以防万一。

那么,为什么每次运行需要大约2.5秒而不是〜0.5?

编辑:这就是我使用threading运行该函数的方法:

threads_list = []
for i in range(num_of_threads):
    t = threading.Thread(target=handle_request)
    threads_list.append(t)

for t in threads_list:
    t.start()

我尝试添加:

for t in threads_list:
    t.join()

但它似乎对表现没有任何影响。

1 个答案:

答案 0 :(得分:0)

问题是,如this blog post中所述,“ CPython解释器上的Python不支持通过多线程进行真正的多核执行。”

使用threading库而不是使用multiprocessing库。在下面的示例中,我所做的只是用对multiprocessing库的调用替换了您的代码。但是,这种方法有一些警告。您将需要使用与multiprocessing库一起使用的实用程序来管理进程之间的通信。 (例如,我很好地利用了multiprocessing.Queue类。)

import multiprocessing

processes_list = []
for _ in range(num_of_processes):
    processes_list.append(multiprocessing.Process(target=handle_request))

for p in processes_list:
    p.start()